diff --git a/client.go b/client.go index a896bed2..f2f2b319 100644 --- a/client.go +++ b/client.go @@ -22,10 +22,8 @@ import ( ) import ( - "github.com/AlexStocks/goext/net" - log "github.com/dubbogo/log4go" "github.com/gorilla/websocket" - jerrors "github.com/juju/errors" + perrors "github.com/pkg/errors" ) const ( @@ -131,7 +129,7 @@ func (c *client) dialTCP() Session { return nil } conn, err = net.DialTimeout("tcp", c.addr, connectTimeout) - if err == nil && gxnet.IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { + if err == nil && IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { conn.Close() err = errSelfConnect } @@ -139,7 +137,7 @@ func (c *client) dialTCP() Session { return newTCPSession(conn, c) } - log.Info("net.DialTimeout(addr:%s, timeout:%v) = error{%s}", c.addr, jerrors.ErrorStack(err)) + log.Infof("net.DialTimeout(addr:%s, timeout:%v) = error:%+v", c.addr, connectTimeout, err) // time.Sleep(connInterval) <-wheel.After(connInterval) } @@ -163,12 +161,12 @@ func (c *client) dialUDP() Session { return nil } conn, err = net.DialUDP("udp", localAddr, peerAddr) - if err == nil && gxnet.IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { + if err == nil && IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { conn.Close() err = errSelfConnect } if err != nil { - log.Warn("net.DialTimeout(addr:%s, timeout:%v) = error{%s}", c.addr, jerrors.ErrorStack(err)) + log.Warnf("net.DialTimeout(addr:%s, timeout:%v) = error:%+v", c.addr, err) // time.Sleep(connInterval) <-wheel.After(connInterval) continue @@ -178,18 +176,18 @@ func (c *client) dialUDP() Session { conn.SetWriteDeadline(time.Now().Add(1e9)) if length, err = conn.Write(connectPingPackage[:]); err != nil { conn.Close() - log.Warn("conn.Write(%s) = {length:%d, err:%s}", string(connectPingPackage), length, jerrors.ErrorStack(err)) + log.Warnf("conn.Write(%s) = {length:%d, err:%+v}", string(connectPingPackage), length, err) // time.Sleep(connInterval) <-wheel.After(connInterval) continue } conn.SetReadDeadline(time.Now().Add(1e9)) length, err = conn.Read(buf) - if netErr, ok := jerrors.Cause(err).(net.Error); ok && netErr.Timeout() { + if netErr, ok := perrors.Cause(err).(net.Error); ok && netErr.Timeout() { err = nil } if err != nil { - log.Info("conn{%#v}.Read() = {length:%d, err:%s}", conn, length, jerrors.ErrorStack(err)) + log.Infof("conn{%#v}.Read() = {length:%d, err:%+v}", conn, length, err) conn.Close() // time.Sleep(connInterval) <-wheel.After(connInterval) @@ -215,8 +213,8 @@ func (c *client) dialWS() Session { return nil } conn, _, err = dialer.Dial(c.addr, nil) - log.Info("websocket.dialer.Dial(addr:%s) = error:%s", c.addr, jerrors.ErrorStack(err)) - if err == nil && gxnet.IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { + log.Infof("websocket.dialer.Dial(addr:%s) = error:%+v", c.addr, err) + if err == nil && IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { conn.Close() err = errSelfConnect } @@ -229,7 +227,7 @@ func (c *client) dialWS() Session { return ss } - log.Info("websocket.dialer.Dial(addr:%s) = error:%s", c.addr, jerrors.ErrorStack(err)) + log.Infof("websocket.dialer.Dial(addr:%s) = error:%+v", c.addr, err) // time.Sleep(connInterval) <-wheel.After(connInterval) } @@ -256,7 +254,7 @@ func (c *client) dialWSS() Session { if c.cert != "" { certPEMBlock, err := ioutil.ReadFile(c.cert) if err != nil { - panic(fmt.Sprintf("ioutil.ReadFile(cert:%s) = error{%s}", c.cert, jerrors.ErrorStack(err))) + panic(fmt.Sprintf("ioutil.ReadFile(cert:%s) = error:%+v", c.cert, err)) } var cert tls.Certificate @@ -278,7 +276,7 @@ func (c *client) dialWSS() Session { for _, c := range config.Certificates { roots, err = x509.ParseCertificates(c.Certificate[len(c.Certificate)-1]) if err != nil { - panic(fmt.Sprintf("error parsing server's root cert: %s\n", jerrors.ErrorStack(err))) + panic(fmt.Sprintf("error parsing server's root cert: %+v\n", err)) } for _, root = range roots { certPool.AddCert(root) @@ -294,7 +292,7 @@ func (c *client) dialWSS() Session { return nil } conn, _, err = dialer.Dial(c.addr, nil) - if err == nil && gxnet.IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { + if err == nil && IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { conn.Close() err = errSelfConnect } @@ -308,7 +306,7 @@ func (c *client) dialWSS() Session { return ss } - log.Info("websocket.dialer.Dial(addr:%s) = error{%s}", c.addr, jerrors.ErrorStack(err)) + log.Infof("websocket.dialer.Dial(addr:%s) = error:%+v", c.addr, err) // time.Sleep(connInterval) <-wheel.After(connInterval) } @@ -399,7 +397,7 @@ func (c *client) reConnect() { // c.Unlock() for { if c.IsClosed() { - log.Warn("client{peer:%s} goroutine exit now.", c.addr) + log.Warnf("client{peer:%s} goroutine exit now.", c.addr) break } diff --git a/conn.go b/conn.go index 8d8dc978..3a66bb59 100644 --- a/conn.go +++ b/conn.go @@ -21,10 +21,9 @@ import ( ) import ( - log "github.com/dubbogo/log4go" "github.com/golang/snappy" "github.com/gorilla/websocket" - jerrors "github.com/juju/errors" + perrors "github.com/pkg/errors" "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" ) @@ -32,7 +31,7 @@ import ( var ( launchTime = time.Now() -// ErrInvalidConnection = errors.New("connection has been closed.") +// ErrInvalidConnection = perrors.New("connection has been closed.") ) ///////////////////////////////////////// @@ -193,10 +192,10 @@ func (t *writeFlusher) Write(p []byte) (int, error) { defer t.lock.Unlock() n, err = t.flusher.Write(p) if err != nil { - return n, jerrors.Trace(err) + return n, perrors.WithStack(err) } if err := t.flusher.Flush(); err != nil { - return 0, jerrors.Trace(err) + return 0, perrors.WithStack(err) } return n, nil @@ -243,16 +242,16 @@ func (t *gettyTCPConn) read(p []byte) (int, error) { currentTime = time.Now() if currentTime.Sub(t.rLastDeadline) > (t.rTimeout >> 2) { if err = t.conn.SetReadDeadline(currentTime.Add(t.rTimeout)); err != nil { - return 0, jerrors.Trace(err) + return 0, perrors.WithStack(err) } t.rLastDeadline = currentTime } } length, err = t.reader.Read(p) - log.Debug("now:%s, length:%d, err:%s", currentTime, length, err) + log.Debugf("now:%s, length:%d, err:%v", currentTime, length, err) atomic.AddUint32(&t.readBytes, uint32(length)) - return length, jerrors.Trace(err) + return length, perrors.WithStack(err) //return length, err } @@ -267,7 +266,7 @@ func (t *gettyTCPConn) Write(pkg interface{}) (int, error) { ) if p, ok = pkg.([]byte); !ok { - return 0, jerrors.Errorf("illegal @pkg{%#v} type", pkg) + return 0, perrors.Errorf("illegal @pkg{%#v} type", pkg) } if t.compress == CompressNone && t.wTimeout > 0 { // Optimization: update write deadline only if more than 25% @@ -276,7 +275,7 @@ func (t *gettyTCPConn) Write(pkg interface{}) (int, error) { currentTime = time.Now() if currentTime.Sub(t.wLastDeadline) > (t.wTimeout >> 2) { if err = t.conn.SetWriteDeadline(currentTime.Add(t.wTimeout)); err != nil { - return 0, jerrors.Trace(err) + return 0, perrors.WithStack(err) } t.wLastDeadline = currentTime } @@ -285,8 +284,8 @@ func (t *gettyTCPConn) Write(pkg interface{}) (int, error) { if length, err = t.writer.Write(p); err == nil { atomic.AddUint32(&t.writeBytes, (uint32)(len(p))) } - log.Debug("now:%s, length:%d, err:%s", currentTime, length, err) - return length, jerrors.Trace(err) + log.Debugf("now:%s, length:%d, err:%v", currentTime, length, err) + return length, perrors.WithStack(err) //return length, err } @@ -299,7 +298,7 @@ func (t *gettyTCPConn) close(waitSec int) { if t.conn != nil { if writer, ok := t.writer.(*snappy.Writer); ok { if err := writer.Close(); err != nil { - log.Error("snappy.Writer.Close() = error{%s}", jerrors.ErrorStack(err)) + log.Errorf("snappy.Writer.Close() = error:%+v", err) } } t.conn.(*net.TCPConn).SetLinger(waitSec) @@ -333,7 +332,7 @@ func setUDPSocketOptions(conn *net.UDPConn) error { err6 := ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true) err4 := ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true) if err6 != nil && err4 != nil { - return jerrors.Trace(err4) + return perrors.WithStack(err4) } return nil } @@ -393,20 +392,20 @@ func (u *gettyUDPConn) read(p []byte) (int, *net.UDPAddr, error) { currentTime = time.Now() if currentTime.Sub(u.rLastDeadline) > (u.rTimeout >> 2) { if err = u.conn.SetReadDeadline(currentTime.Add(u.rTimeout)); err != nil { - return 0, nil, jerrors.Trace(err) + return 0, nil, perrors.WithStack(err) } u.rLastDeadline = currentTime } } length, addr, err = u.conn.ReadFromUDP(p) // connected udp also can get return @addr - log.Debug("ReadFromUDP() = {length:%d, peerAddr:%s, error:%s}", length, addr, err) + log.Debugf("ReadFromUDP() = {length:%d, peerAddr:%s, error:%v}", length, addr, err) if err == nil { atomic.AddUint32(&u.readBytes, uint32(length)) } //return length, addr, err - return length, addr, jerrors.Trace(err) + return length, addr, perrors.WithStack(err) } // write udp packet, @ctx should be of type UDPContext @@ -422,10 +421,10 @@ func (u *gettyUDPConn) Write(udpCtx interface{}) (int, error) { ) if ctx, ok = udpCtx.(UDPContext); !ok { - return 0, jerrors.Errorf("illegal @udpCtx{%s} type, @udpCtx type:%T", udpCtx, udpCtx) + return 0, perrors.Errorf("illegal @udpCtx{%s} type, @udpCtx type:%T", udpCtx, udpCtx) } if buf, ok = ctx.Pkg.([]byte); !ok { - return 0, jerrors.Errorf("illegal @udpCtx.Pkg{%#v} type", udpCtx) + return 0, perrors.Errorf("illegal @udpCtx.Pkg{%#v} type", udpCtx) } if u.ss.EndPoint().EndPointType() == UDP_ENDPOINT { peerAddr = ctx.PeerAddr @@ -441,7 +440,7 @@ func (u *gettyUDPConn) Write(udpCtx interface{}) (int, error) { currentTime = time.Now() if currentTime.Sub(u.wLastDeadline) > (u.wTimeout >> 2) { if err = u.conn.SetWriteDeadline(currentTime.Add(u.wTimeout)); err != nil { - return 0, jerrors.Trace(err) + return 0, perrors.WithStack(err) } u.wLastDeadline = currentTime } @@ -450,9 +449,9 @@ func (u *gettyUDPConn) Write(udpCtx interface{}) (int, error) { if length, _, err = u.conn.WriteMsgUDP(buf, nil, peerAddr); err == nil { atomic.AddUint32(&u.writeBytes, (uint32)(len(buf))) } - log.Debug("WriteMsgUDP(peerAddr:%s) = {length:%d, error:%s}", peerAddr, length, err) + log.Debugf("WriteMsgUDP(peerAddr:%s) = {length:%d, error:%v}", peerAddr, length, err) - return length, jerrors.Trace(err) + return length, perrors.WithStack(err) //return length, err } @@ -529,7 +528,7 @@ func (w *gettyWSConn) handlePing(message string) error { w.UpdateActive() } - return jerrors.Trace(err) + return perrors.WithStack(err) } func (w *gettyWSConn) handlePong(string) error { @@ -546,11 +545,11 @@ func (w *gettyWSConn) read() ([]byte, error) { w.incReadPkgNum() } else { if websocket.IsUnexpectedCloseError(e, websocket.CloseGoingAway) { - log.Warn("websocket unexpected close error: %v", e) + log.Warnf("websocket unexpected close error: %v", e) } } - return b, jerrors.Trace(e) + return b, perrors.WithStack(e) //return b, e } @@ -567,7 +566,7 @@ func (w *gettyWSConn) updateWriteDeadline() error { currentTime = time.Now() if currentTime.Sub(w.wLastDeadline) > (w.wTimeout >> 2) { if err = w.conn.SetWriteDeadline(currentTime.Add(w.wTimeout)); err != nil { - return jerrors.Trace(err) + return perrors.WithStack(err) } w.wLastDeadline = currentTime } @@ -585,25 +584,25 @@ func (w *gettyWSConn) Write(pkg interface{}) (int, error) { ) if p, ok = pkg.([]byte); !ok { - return 0, jerrors.Errorf("illegal @pkg{%#v} type", pkg) + return 0, perrors.Errorf("illegal @pkg{%#v} type", pkg) } w.updateWriteDeadline() if err = w.conn.WriteMessage(websocket.BinaryMessage, p); err == nil { atomic.AddUint32(&w.writeBytes, (uint32)(len(p))) } - return len(p), jerrors.Trace(err) + return len(p), perrors.WithStack(err) //return len(p), err } func (w *gettyWSConn) writePing() error { w.updateWriteDeadline() - return jerrors.Trace(w.conn.WriteMessage(websocket.PingMessage, []byte{})) + return perrors.WithStack(w.conn.WriteMessage(websocket.PingMessage, []byte{})) } func (w *gettyWSConn) writePong(message []byte) error { w.updateWriteDeadline() - return jerrors.Trace(w.conn.WriteMessage(websocket.PongMessage, message)) + return perrors.WithStack(w.conn.WriteMessage(websocket.PongMessage, message)) } // close websocket connection diff --git a/getty.go b/getty.go index 7f88b449..3bf1d4eb 100644 --- a/getty.go +++ b/getty.go @@ -11,9 +11,10 @@ package getty import ( "compress/flate" - "errors" "net" "time" + + perrors "github.com/pkg/errors" ) // NewSessionCallback will be invoked when server accepts a new client connection or client connects to server successfully. @@ -119,9 +120,9 @@ type Connection interface { ///////////////////////////////////////// var ( - ErrSessionClosed = errors.New("session Already Closed") - ErrSessionBlocked = errors.New("session Full Blocked") - ErrNullPeerAddr = errors.New("peer address is nil") + ErrSessionClosed = perrors.New("session Already Closed") + ErrSessionBlocked = perrors.New("session Full Blocked") + ErrNullPeerAddr = perrors.New("peer address is nil") ) type Session interface { diff --git a/go.mod b/go.mod index 4c45bb86..f45011a8 100644 --- a/go.mod +++ b/go.mod @@ -1,19 +1,12 @@ module github.com/dubbogo/getty require ( - github.com/AlexStocks/getty v1.0.4 - github.com/AlexStocks/goext v0.3.2 - github.com/AlexStocks/log4go v1.0.2 - github.com/dubbogo/log4go v0.0.0-20190406152735-41c57e1073e9 - github.com/fatih/camelcase v1.0.0 // indirect - github.com/fatih/structs v1.1.0 // indirect - github.com/gogo/protobuf v1.2.1 github.com/golang/snappy v0.0.1 github.com/gorilla/websocket v1.4.0 - github.com/juju/errors v0.0.0-20190207033735-e65537c515d7 - github.com/k0kubun/pp v3.0.1+incompatible // indirect - github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7 - go.etcd.io/etcd v3.3.13+incompatible // indirect + github.com/pkg/errors v0.8.1 + github.com/stretchr/testify v1.3.0 // indirect + go.uber.org/atomic v1.4.0 // indirect + go.uber.org/multierr v1.1.0 // indirect + go.uber.org/zap v1.10.0 golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53 - gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index e332567b..99ebff79 100644 --- a/go.sum +++ b/go.sum @@ -1,187 +1,26 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/AlexStocks/getty v1.0.4 h1:SGv/6104d1GHAi5cm24Q50H9jsXZzEnNX1cmRno7N8s= -github.com/AlexStocks/getty v1.0.4/go.mod h1:n25mdqPgFi06sWL6mZTjm1hBIZuKwgXUVXAX+KGB97U= -github.com/AlexStocks/goext v0.3.2 h1:Bn4C+R6/E5Yjk2Uc/voawtbGv91x9aCid92xwYL2AS0= -github.com/AlexStocks/goext v0.3.2/go.mod h1:3M5j9Pjge4CdkNg2WIjRLUeoPedJHHKwkkglDGSl3Hc= -github.com/AlexStocks/log4go v1.0.2 h1:1K5WM8KjSUECaoXUl8FSF05KGeCJDfBrhKUBsxwUvhk= -github.com/AlexStocks/log4go v1.0.2/go.mod h1:6kCCRo/orDo8mh5CEDOeuSSM674wBQ8M6E0K8dVOIz4= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.12+incompatible h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ= -github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190318101727-c7c1946145b6 h1:IIw7G/PU3uHfnCgFRU1IvSicOeKBV6zc+5BeMxoBD/E= -github.com/coreos/go-systemd v0.0.0-20190318101727-c7c1946145b6/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dubbogo/log4go v0.0.0-20190406152735-41c57e1073e9 h1:RCRkCLJPUZNyAHLEEJvbFrNkyzmmzFnrRbk+eGvUwNQ= -github.com/dubbogo/log4go v0.0.0-20190406152735-41c57e1073e9/go.mod h1:iyyiSbUgJZcUgpt4hQs7YHZUop6982EGjQxIBeEmevQ= -github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= -github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= -github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= -github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:BWIsLfhgKhV5g/oF34aRjniBHLTZe5DNekSjbAjIS6c= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= -github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= -github.com/juju/errors v0.0.0-20190207033735-e65537c515d7 h1:dMIPRDg6gi7CUp0Kj2+HxqJ5kTr1iAdzsXYIrLCNSmU= -github.com/juju/errors v0.0.0-20190207033735-e65537c515d7/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= -github.com/juju/loggo v0.0.0-20190212223446-d976af380377 h1:n6QjW3g5JNY3xPmIjFt6z1H6tFQA6BhwOC2bvTAm1YU= -github.com/juju/loggo v0.0.0-20190212223446-d976af380377/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= -github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= -github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 h1:WQM1NildKThwdP7qWrNAFGzp4ijNLw8RlgENkaI4MJs= -github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= -github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= -github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/k0kubun/pp v3.0.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= -github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40= -github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7 h1:SWlt7BoQNASbhTUD0Oy5yysI2seJ7vWuGUp///OM4TM= -github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7/go.mod h1:Y2SaZf2Rzd0pXkLVhLlCiAXFCLSXAIbTKDivVgff/AM= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 h1:wL11wNW7dhKIcRCHSm4sHKPWz0tt4mwBsVodG7+Xyqg= -github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/name5566/leaf v0.0.0-20181103040206-1364c176dfbd/go.mod h1:JrOIxq3vDxvtuEI7Kmm2yqkuBfuT9DMLFMnCyYHLaKM= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY= -github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= -github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= -github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 h1:vG/gY/PxA3v3l04qxe3tDjXyu3bozii8ulSlIPOYKhI= -github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v3.3.13+incompatible h1:jCejD5EMnlGxFvcGRyEV4VGlENZc7oPQX6o0t7n3xbw= -go.etcd.io/etcd v3.3.13+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI= -go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53 h1:kcXqo9vE6fsZY5X5Rd7R1l7fTgnWaDCVmln65REefiE= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= -gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/logger.go b/logger.go new file mode 100644 index 00000000..42c5dea8 --- /dev/null +++ b/logger.go @@ -0,0 +1,112 @@ +package getty + +import ( + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +// Logger for user who want to customize logger of getty +type Logger interface { + Info(args ...interface{}) + Warn(args ...interface{}) + Error(args ...interface{}) + Debug(args ...interface{}) + + Infof(fmt string, args ...interface{}) + Warnf(fmt string, args ...interface{}) + Errorf(fmt string, args ...interface{}) + Debugf(fmt string, args ...interface{}) +} + +type LoggerLevel int8 + +const ( + // DebugLevel logs are typically voluminous, and are usually disabled in + // production. + LoggerLevelDebug = LoggerLevel(zapcore.DebugLevel) + // InfoLevel is the default logging priority. + LoggerLevelInfo = LoggerLevel(zapcore.InfoLevel) + // WarnLevel logs are more important than Infof, but don't need individual + // human review. + LoggerLevelWarn = LoggerLevel(zapcore.WarnLevel) + // ErrorLevel logs are high-priority. If an application is running smoothly, + // it shouldn't generate any error-level logs. + LoggerLevelError = LoggerLevel(zapcore.ErrorLevel) + // DPanicLevel logs are particularly important errors. In development the + // logger panics after writing the message. + LoggerLevelDPanic = LoggerLevel(zapcore.DPanicLevel) + // PanicLevel logs a message, then panics. + LoggerLevelPanic = LoggerLevel(zapcore.PanicLevel) + // FatalLevel logs a message, then calls os.Exit(1). + LoggerLevelFatal = LoggerLevel(zapcore.FatalLevel) +) + +var ( + log Logger + zapLogger *zap.Logger + + zapLoggerConfig = zap.NewDevelopmentConfig() + zapLoggerEncoderConfig = zapcore.EncoderConfig{ + TimeKey: "time", + LevelKey: "level", + NameKey: "logger", + CallerKey: "caller", + MessageKey: "message", + StacktraceKey: "stacktrace", + EncodeLevel: zapcore.CapitalColorLevelEncoder, + EncodeTime: zapcore.ISO8601TimeEncoder, + EncodeDuration: zapcore.SecondsDurationEncoder, + EncodeCaller: zapcore.ShortCallerEncoder, + } +) + +func init() { + zapLoggerConfig.EncoderConfig = zapLoggerEncoderConfig + zapLogger, _ = zapLoggerConfig.Build() + log = zapLogger.Sugar() + + // todo: flushes buffer when redirect log to file. + // var exitSignal = make(chan os.Signal) + // signal.Notify(exitSignal, syscall.SIGTERM, syscall.SIGINT) + // go func() { + // <-exitSignal + // // Sync calls the underlying Core's Sync method, flushing any buffered log + // // entries. Applications should take care to call Sync before exiting. + // err := zapLogger.Sync() // flushes buffer, if any + // if err != nil { + // fmt.Printf("zapLogger sync err: %+v", perrors.WithStack(err)) + // } + // os.Exit(0) + // }() +} + +// SetLogger: customize yourself logger. +func SetLogger(logger Logger) { + log = logger +} + +// SetLoggerLevel +func SetLoggerLevel(level LoggerLevel) error { + var err error + zapLoggerConfig.Level = zap.NewAtomicLevelAt(zapcore.Level(level)) + zapLogger, err = zapLoggerConfig.Build() + if err != nil { + return err + } + log = zapLogger.Sugar() + return nil +} + +// SetLoggerCallerDisable: disable caller info in production env for performance improve. +// It is highly recommended that you execute this method in a production environment. +func SetLoggerCallerDisable() error { + var err error + zapLoggerConfig.Development = false + zapLoggerConfig.DisableCaller = true + zapLogger, err = zapLoggerConfig.Build() + if err != nil { + return err + } + log = zapLogger.Sugar() + return nil +} diff --git a/options.go b/options.go index a6bad623..cd5959c0 100644 --- a/options.go +++ b/options.go @@ -68,9 +68,9 @@ func WithWebsocketServerRootCert(cert string) ServerOption { type ClientOption func(*ClientOptions) type ClientOptions struct { - addr string - number int - reconnectInterval int// reConnect Interval + addr string + number int + reconnectInterval int // reConnect Interval // the cert file of wss server which may contain server domain, server ip, the starting effective date, effective // duration, the hash alg, the len of the private key. diff --git a/server.go b/server.go index a36ea554..8610e5b6 100644 --- a/server.go +++ b/server.go @@ -22,16 +22,13 @@ import ( ) import ( - "github.com/AlexStocks/goext/net" - "github.com/AlexStocks/goext/time" - log "github.com/dubbogo/log4go" "github.com/gorilla/websocket" - jerrors "github.com/juju/errors" + perrors "github.com/pkg/errors" ) var ( - errSelfConnect = jerrors.New("connect self!") - serverFastFailTimeout = gxtime.TimeSecondDuration(1) + errSelfConnect = perrors.New("connect self!") + serverFastFailTimeout = time.Second * 1 ) type server struct { @@ -119,7 +116,7 @@ func (s *server) stop() { if err = s.server.Shutdown(ctx); err != nil { // if the log output is "shutdown ctx: context deadline exceeded", it means that // there are still some active connections. - log.Error("server shutdown ctx:%s error:%s", ctx, err) + log.Errorf("server shutdown ctx:%s error:%v", ctx, err) } } s.server = nil @@ -157,7 +154,7 @@ func (s *server) listenTCP() error { streamListener, err = net.Listen("tcp", s.addr) if err != nil { - return jerrors.Annotatef(err, "net.Listen(tcp, addr:%s))", s.addr) + return perrors.Wrapf(err, "net.Listen(tcp, addr:%s))", s.addr) } s.streamListener = streamListener @@ -174,14 +171,14 @@ func (s *server) listenUDP() error { localAddr, err = net.ResolveUDPAddr("udp", s.addr) if err != nil { - return jerrors.Annotatef(err, "net.ResolveUDPAddr(udp, addr:%s)", s.addr) + return perrors.Wrapf(err, "net.ResolveUDPAddr(udp, addr:%s)", s.addr) } pktListener, err = net.ListenUDP("udp", localAddr) if err != nil { - return jerrors.Annotatef(err, "net.ListenUDP((udp, localAddr:%#v)", localAddr) + return perrors.Wrapf(err, "net.ListenUDP((udp, localAddr:%#v)", localAddr) } // if err = setUDPSocketOptions(pktListener); err != nil { - // return errors.Wrapf(err, "setUDPSocketOptions(pktListener:%#v)", pktListener) + // return perrors.Wrapf(err, "setUDPSocketOptions(pktListener:%#v)", pktListener) // } s.pktListener = pktListener @@ -193,9 +190,9 @@ func (s *server) listenUDP() error { func (s *server) listen() error { switch s.endPointType { case TCP_SERVER, WS_SERVER, WSS_SERVER: - return jerrors.Trace(s.listenTCP()) + return perrors.WithStack(s.listenTCP()) case UDP_ENDPOINT: - return jerrors.Trace(s.listenUDP()) + return perrors.WithStack(s.listenUDP()) } return nil @@ -204,10 +201,10 @@ func (s *server) listen() error { func (s *server) accept(newSession NewSessionCallback) (Session, error) { conn, err := s.streamListener.Accept() if err != nil { - return nil, jerrors.Trace(err) + return nil, perrors.WithStack(err) } - if gxnet.IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { - log.Warn("conn.localAddr{%s} == conn.RemoteAddr", conn.LocalAddr().String(), conn.RemoteAddr().String()) + if IsSameAddr(conn.RemoteAddr(), conn.LocalAddr()) { + log.Warnf("conn.localAddr{%s} == conn.RemoteAddr", conn.LocalAddr().String(), conn.RemoteAddr().String()) return nil, errSelfConnect } @@ -215,7 +212,7 @@ func (s *server) accept(newSession NewSessionCallback) (Session, error) { err = newSession(ss) if err != nil { conn.Close() - return nil, jerrors.Trace(err) + return nil, perrors.WithStack(err) } return ss, nil @@ -232,7 +229,7 @@ func (s *server) runTcpEventLoop(newSession NewSessionCallback) { ) for { if s.IsClosed() { - log.Warn("server{%s} stop acceptting client connect request.", s.addr) + log.Warnf("server{%s} stop acceptting client connect request.", s.addr) return } if delay != 0 { @@ -252,7 +249,7 @@ func (s *server) runTcpEventLoop(newSession NewSessionCallback) { } continue } - log.Warn("server{%s}.Accept() = err {%#v}", s.addr, jerrors.ErrorStack(err)) + log.Warnf("server{%s}.Accept() = err {%+v}", s.addr, err) continue } delay = 0 @@ -303,17 +300,17 @@ func (s *wsHandler) serveWSRequest(w http.ResponseWriter, r *http.Request) { if s.server.IsClosed() { http.Error(w, "HTTP server is closed(code:500-11).", 500) - log.Warn("server{%s} stop acceptting client connect request.", s.server.addr) + log.Warnf("server{%s} stop acceptting client connect request.", s.server.addr) return } conn, err := s.upgrader.Upgrade(w, r, nil) if err != nil { - log.Warn("upgrader.Upgrader(http.Request{%#v}) = error{%s}", r, err) + log.Warnf("upgrader.Upgrader(http.Request{%#v}) = error:%+v", r, err) return } if conn.RemoteAddr().String() == conn.LocalAddr().String() { - log.Warn("conn.localAddr{%s} == conn.RemoteAddr", conn.LocalAddr().String(), conn.RemoteAddr().String()) + log.Warnf("conn.localAddr{%s} == conn.RemoteAddr", conn.LocalAddr().String(), conn.RemoteAddr().String()) return } // conn.SetReadLimit(int64(handler.maxMsgLen)) @@ -321,7 +318,7 @@ func (s *wsHandler) serveWSRequest(w http.ResponseWriter, r *http.Request) { err = s.newSession(ss) if err != nil { conn.Close() - log.Warn("server{%s}.newSession(ss{%#v}) = err {%s}", s.server.addr, ss, err) + log.Warnf("server{%s}.newSession(ss{%#v}) = err {%s}", s.server.addr, ss, err) return } if ss.(*session).maxMsgLen > 0 { @@ -355,7 +352,7 @@ func (s *server) runWSEventLoop(newSession NewSessionCallback) { s.lock.Unlock() err = server.Serve(s.streamListener) if err != nil { - log.Error("http.server.Serve(addr{%s}) = err{%s}", s.addr, jerrors.ErrorStack(err)) + log.Errorf("http.server.Serve(addr{%s}) = err{%+v}", s.addr, err) // panic(err) } }() @@ -378,8 +375,8 @@ func (s *server) runWSSEventLoop(newSession NewSessionCallback) { defer s.wg.Done() if certificate, err = tls.LoadX509KeyPair(s.cert, s.privateKey); err != nil { - panic(fmt.Sprintf("tls.LoadX509KeyPair(cert{%s}, privateKey{%s}) = err{%s}", - s.cert, s.privateKey, jerrors.ErrorStack(err))) + panic(fmt.Sprintf("tls.LoadX509KeyPair(cert{%s}, privateKey{%s}) = err{%+v}", + s.cert, s.privateKey, err)) return } config = &tls.Config{ @@ -392,7 +389,7 @@ func (s *server) runWSSEventLoop(newSession NewSessionCallback) { if s.caCert != "" { certPem, err = ioutil.ReadFile(s.caCert) if err != nil { - panic(fmt.Errorf("ioutil.ReadFile(certFile{%s}) = err{%s}", s.caCert, jerrors.ErrorStack(err))) + panic(fmt.Errorf("ioutil.ReadFile(certFile{%s}) = err{%+v}", s.caCert, err)) } certPool = x509.NewCertPool() if ok := certPool.AppendCertsFromPEM(certPem); !ok { @@ -417,7 +414,7 @@ func (s *server) runWSSEventLoop(newSession NewSessionCallback) { s.lock.Unlock() err = server.Serve(tls.NewListener(s.streamListener, config)) if err != nil { - log.Error("http.server.Serve(addr{%s}) = err{%s}", s.addr, jerrors.ErrorStack(err)) + log.Errorf("http.server.Serve(addr{%s}) = err{%+v}", s.addr, err) panic(err) } }() @@ -427,7 +424,7 @@ func (s *server) runWSSEventLoop(newSession NewSessionCallback) { // @newSession: new connection callback func (s *server) RunEventLoop(newSession NewSessionCallback) { if err := s.listen(); err != nil { - panic(fmt.Errorf("server.listen() = error:%s", jerrors.ErrorStack(err))) + panic(fmt.Errorf("server.listen() = error:%+v", err)) } switch s.endPointType { diff --git a/session.go b/session.go index 024c0be7..6d10254b 100644 --- a/session.go +++ b/session.go @@ -20,14 +20,8 @@ import ( ) import ( - log "github.com/dubbogo/log4go" "github.com/gorilla/websocket" - jerrors "github.com/juju/errors" -) - -import ( - "github.com/AlexStocks/goext/context" - "github.com/AlexStocks/goext/time" + perrors "github.com/pkg/errors" ) const ( @@ -48,10 +42,10 @@ const ( ///////////////////////////////////////// var ( - wheel = gxtime.NewWheel(gxtime.TimeMillisecondDuration(100), 1200) // wheel longest span is 2 minute + wheel = NewWheel(time.Millisecond*100, 1200) // wheel longest span is 2 minute ) -func GetTimeWheel() *gxtime.Wheel { +func GetTimeWheel() *Wheel { return wheel } @@ -76,7 +70,7 @@ type session struct { wQ chan interface{} // attribute - attrs *gxcontext.ValuesContext + attrs *ValuesContext // goroutines sync grNum int32 lock sync.RWMutex @@ -91,7 +85,7 @@ func newSession(endPoint EndPoint, conn Connection) *session { done: make(chan struct{}), period: period, wait: pendingDuration, - attrs: gxcontext.NewValuesContext(nil), + attrs: NewValuesContext(nil), } ss.Connection.setSession(ss) @@ -132,7 +126,7 @@ func (s *session) Reset() { // s.errFlag = false s.period = period s.wait = pendingDuration - s.attrs = gxcontext.NewValuesContext(nil) + s.attrs = NewValuesContext(nil) s.grNum = 0 s.SetWriteTimeout(netIOTimeout) @@ -251,7 +245,7 @@ func (s *session) SetRQLen(readQLen int) { s.lock.Lock() s.rQ = make(chan interface{}, readQLen) s.lock.Unlock() - log.Debug("%s, [session.SetRQLen] rQ{len:%d, cap:%d}", s.Stat(), len(s.rQ), cap(s.rQ)) + log.Debugf("%s, [session.SetRQLen] rQ{len:%d, cap:%d}", s.Stat(), len(s.rQ), cap(s.rQ)) } // set @session's Write queue size @@ -263,7 +257,7 @@ func (s *session) SetWQLen(writeQLen int) { s.lock.Lock() s.wQ = make(chan interface{}, writeQLen) s.lock.Unlock() - log.Debug("%s, [session.SetWQLen] wQ{len:%d, cap:%d}", s.Stat(), len(s.wQ), cap(s.wQ)) + log.Debugf("%s, [session.SetWQLen] wQ{len:%d, cap:%d}", s.Stat(), len(s.wQ), cap(s.wQ)) } // set maximum wait time when session got error or got exit signal @@ -327,7 +321,7 @@ func (s *session) WritePkg(pkg interface{}, timeout time.Duration) error { const size = 64 << 10 rBuf := make([]byte, size) rBuf = rBuf[:runtime.Stack(rBuf, false)] - log.Error("[session.WritePkg] panic session %s: err=%s\n%s", s.sessionToken(), r, rBuf) + log.Errorf("[session.WritePkg] panic session %s: err=%s\n%s", s.sessionToken(), r, rBuf) } }() @@ -337,14 +331,14 @@ func (s *session) WritePkg(pkg interface{}, timeout time.Duration) error { s.incWritePkgNum() // gxlog.CError("after incWritePkgNum, ss:%s", s.Stat()) } - return jerrors.Trace(err) + return perrors.WithStack(err) } select { case s.wQ <- pkg: break // for possible gen a new pkg case <-wheel.After(timeout): - log.Warn("%s, [session.WritePkg] wQ{len:%d, cap:%d}", s.Stat(), len(s.wQ), cap(s.wQ)) + log.Warnf("%s, [session.WritePkg] wQ{len:%d, cap:%d}", s.Stat(), len(s.wQ), cap(s.wQ)) return ErrSessionBlocked } @@ -359,7 +353,7 @@ func (s *session) WriteBytes(pkg []byte) error { // s.conn.SetWriteTimeout(time.Now().Add(s.wTimeout)) if _, err := s.Connection.Write(pkg); err != nil { - return jerrors.Annotatef(err, "s.Connection.Write(pkg len:%d)", len(pkg)) + return perrors.Wrapf(err, "s.Connection.Write(pkg len:%d)", len(pkg)) } s.incWritePkgNum() @@ -400,7 +394,7 @@ func (s *session) WriteBytesArray(pkgs ...[]byte) error { // return s.Connection.Write(arr) if err = s.WriteBytes(arr); err != nil { - return jerrors.Trace(err) + return perrors.WithStack(err) } num := len(pkgs) - 1 @@ -446,7 +440,7 @@ func (s *session) handleLoop() { wsFlag bool wsConn *gettyWSConn // start time.Time - counter gxtime.CountWatch + counter CountWatch inPkg interface{} outPkg interface{} ) @@ -458,14 +452,14 @@ func (s *session) handleLoop() { const size = 64 << 10 rBuf := make([]byte, size) rBuf = rBuf[:runtime.Stack(rBuf, false)] - log.Error("[session.handleLoop] panic session %s: err=%s\n%s", s.sessionToken(), r, rBuf) + log.Errorf("[session.handleLoop] panic session %s: err=%s\n%s", s.sessionToken(), r, rBuf) } grNum = atomic.AddInt32(&(s.grNum), -1) // if !s.errFlag { s.listener.OnClose(s) // } - log.Info("%s, [session.handleLoop] goroutine exit now, left gr num %d", s.Stat(), grNum) + log.Infof("%s, [session.handleLoop] goroutine exit now, left gr num %d", s.Stat(), grNum) s.gc() }() @@ -480,13 +474,13 @@ LOOP: // this case branch assure the (session)handleLoop gr will exit before (session)handlePackage gr. if atomic.LoadInt32(&(s.grNum)) == 1 { // make sure @(session)handlePackage goroutine has been closed. if len(s.rQ) == 0 && len(s.wQ) == 0 { - log.Info("%s, [session.handleLoop] got done signal. Both rQ and wQ are nil.", s.Stat()) + log.Infof("%s, [session.handleLoop] got done signal. Both rQ and wQ are nil.", s.Stat()) break LOOP } counter.Start() // if time.Since(start).Nanoseconds() >= s.wait.Nanoseconds() { if counter.Count() > s.wait.Nanoseconds() { - log.Info("%s, [session.handleLoop] got done signal ", s.Stat()) + log.Infof("%s, [session.handleLoop] got done signal ", s.Stat()) break LOOP } } @@ -494,26 +488,26 @@ LOOP: case inPkg = <-s.rQ: // read the s.rQ and assure (session)handlePackage gr will not block by (session)rQ. if flag { - log.Debug("%#v <-s.rQ", inPkg) + log.Debugf("%#v <-s.rQ", inPkg) pkg := inPkg // go s.listener.OnMessage(s, pkg) s.listener.OnMessage(s, pkg) s.incReadPkgNum() } else { - log.Info("[session.handleLoop] drop readin package{%#v}", inPkg) + log.Infof("[session.handleLoop] drop readin package{%#v}", inPkg) } case outPkg = <-s.wQ: if flag { if err = s.writer.Write(s, outPkg); err != nil { - log.Error("%s, [session.handleLoop] = error{%s}", s.sessionToken(), jerrors.ErrorStack(err)) + log.Errorf("%s, [session.handleLoop] = error:%+v", s.sessionToken(), err) s.stop() flag = false // break LOOP } s.incWritePkgNum() } else { - log.Info("[session.handleLoop] drop writeout package{%#v}", outPkg) + log.Infof("[session.handleLoop] drop writeout package{%#v}", outPkg) } case <-wheel.After(s.period): @@ -521,7 +515,7 @@ LOOP: if wsFlag { err := wsConn.writePing() if err != nil { - log.Warn("wsConn.writePing() = error{%s}", err) + log.Warnf("wsConn.writePing() = error{%s}", err) } } s.listener.OnCron(s) @@ -542,14 +536,14 @@ func (s *session) handlePackage() { const size = 64 << 10 rBuf := make([]byte, size) rBuf = rBuf[:runtime.Stack(rBuf, false)] - log.Error("[session.handlePackage] panic session %s: err=%s\n%s", s.sessionToken(), r, rBuf) + log.Errorf("[session.handlePackage] panic session %s: err=%s\n%s", s.sessionToken(), r, rBuf) } grNum = atomic.AddInt32(&(s.grNum), -1) - log.Info("%s, [session.handlePackage] gr will exit now, left gr num %d", s.sessionToken(), grNum) + log.Infof("%s, [session.handlePackage] gr will exit now, left gr num %d", s.sessionToken(), grNum) s.stop() if err != nil { - log.Error("%s, [session.handlePackage] error{%s}", s.sessionToken(), jerrors.ErrorStack(err)) + log.Errorf("%s, [session.handlePackage] error:%+v", s.sessionToken(), err) s.listener.OnError(s, err) } }() @@ -603,10 +597,10 @@ func (s *session) handleTCPPackage() error { // s.conn.SetReadTimeout(time.Now().Add(s.rTimeout)) bufLen, err = conn.read(buf) if err != nil { - if netError, ok = jerrors.Cause(err).(net.Error); ok && netError.Timeout() { + if netError, ok = perrors.Cause(err).(net.Error); ok && netError.Timeout() { break } - log.Error("%s, [session.conn.read] = error{%s}", s.sessionToken(), jerrors.ErrorStack(err)) + log.Errorf("%s, [session.conn.read] = error:%+v", s.sessionToken(), err) // for (Codec)OnErr // s.errFlag = true exit = true @@ -627,11 +621,11 @@ func (s *session) handleTCPPackage() error { // pkg, err = s.pkgHandler.Read(s, pktBuf) pkg, pkgLen, err = s.reader.Read(s, pktBuf.Bytes()) if err == nil && s.maxMsgLen > 0 && pkgLen > int(s.maxMsgLen) { - err = jerrors.Errorf("pkgLen %d > session max message len %d", pkgLen, s.maxMsgLen) + err = perrors.Errorf("pkgLen %d > session max message len %d", pkgLen, s.maxMsgLen) } if err != nil { - log.Warn("%s, [session.handleTCPPackage] = len{%d}, error{%s}", - s.sessionToken(), pkgLen, jerrors.ErrorStack(err)) + log.Warnf("%s, [session.handleTCPPackage] = len{%d}, error:%+v", + s.sessionToken(), pkgLen, err) // for (Codec)OnErr // s.errFlag = true exit = true @@ -649,7 +643,7 @@ func (s *session) handleTCPPackage() error { } } - return jerrors.Trace(err) + return perrors.WithStack(err) } // get package from udp packet @@ -678,39 +672,39 @@ func (s *session) handleUDPPackage() error { } bufLen, addr, err = conn.read(buf) - log.Debug("conn.read() = bufLen:%d, addr:%#v, err:%s", bufLen, addr, jerrors.ErrorStack(err)) - if netError, ok = jerrors.Cause(err).(net.Error); ok && netError.Timeout() { + log.Debugf("conn.read() = bufLen:%d, addr:%#v, err:%+v", bufLen, addr, err) + if netError, ok = perrors.Cause(err).(net.Error); ok && netError.Timeout() { continue } if err != nil { - log.Error("%s, [session.handleUDPPackage] = len{%d}, error{%s}", - s.sessionToken(), bufLen, jerrors.ErrorStack(err)) - err = jerrors.Annotatef(err, "conn.read()") + log.Errorf("%s, [session.handleUDPPackage] = len{%d}, error{%+s}", + s.sessionToken(), bufLen, err) + err = perrors.Wrapf(err, "conn.read()") break } if bufLen == 0 { - log.Error("conn.read() = bufLen:%d, addr:%s, err:%s", bufLen, addr, jerrors.ErrorStack(err)) + log.Errorf("conn.read() = bufLen:%d, addr:%s, err:%+v", bufLen, addr, err) continue } if bufLen == len(connectPingPackage) && bytes.Equal(connectPingPackage, buf[:bufLen]) { - log.Info("got %s connectPingPackage", addr) + log.Infof("got %s connectPingPackage", addr) continue } pkg, pkgLen, err = s.reader.Read(s, buf[:bufLen]) - log.Debug("s.reader.Read() = pkg:%#v, pkgLen:%d, err:%s", pkg, pkgLen, jerrors.ErrorStack(err)) + log.Debugf("s.reader.Read() = pkg:%#v, pkgLen:%d, err:%+v", pkg, pkgLen, err) if err == nil && s.maxMsgLen > 0 && bufLen > int(s.maxMsgLen) { - err = jerrors.Errorf("Message Too Long, bufLen %d, session max message len %d", bufLen, s.maxMsgLen) + err = perrors.Errorf("Message Too Long, bufLen %d, session max message len %d", bufLen, s.maxMsgLen) } if err != nil { - log.Warn("%s, [session.handleUDPPackage] = len{%d}, error{%s}", - s.sessionToken(), pkgLen, jerrors.ErrorStack(err)) + log.Warnf("%s, [session.handleUDPPackage] = len{%d}, error:%+v", + s.sessionToken(), pkgLen, err) continue } if pkgLen == 0 { - log.Error("s.reader.Read() = pkg:%#v, pkgLen:%d, err:%s", pkg, pkgLen, jerrors.ErrorStack(err)) + log.Errorf("s.reader.Read() = pkg:%#v, pkgLen:%d, err:%+v", pkg, pkgLen, err) continue } @@ -718,7 +712,7 @@ func (s *session) handleUDPPackage() error { s.rQ <- UDPContext{Pkg: pkg, PeerAddr: addr} } - return jerrors.Trace(err) + return perrors.WithStack(err) } // get package from websocket stream @@ -739,24 +733,24 @@ func (s *session) handleWSPackage() error { break } pkg, err = conn.read() - if netError, ok = jerrors.Cause(err).(net.Error); ok && netError.Timeout() { + if netError, ok = perrors.Cause(err).(net.Error); ok && netError.Timeout() { continue } if err != nil { - log.Warn("%s, [session.handleWSPackage] = error{%s}", - s.sessionToken(), jerrors.ErrorStack(err)) + log.Warnf("%s, [session.handleWSPackage] = error{%+s}", + s.sessionToken(), err) // s.errFlag = true - return jerrors.Trace(err) + return perrors.WithStack(err) } s.UpdateActive() if s.reader != nil { unmarshalPkg, length, err = s.reader.Read(s, pkg) if err == nil && s.maxMsgLen > 0 && length > int(s.maxMsgLen) { - err = jerrors.Errorf("Message Too Long, length %d, session max message len %d", length, s.maxMsgLen) + err = perrors.Errorf("Message Too Long, length %d, session max message len %d", length, s.maxMsgLen) } if err != nil { - log.Warn("%s, [session.handleWSPackage] = len{%d}, error{%s}", - s.sessionToken(), length, jerrors.ErrorStack(err)) + log.Warnf("%s, [session.handleWSPackage] = len{%d}, error:%+v", + s.sessionToken(), length, err) continue } s.rQ <- unmarshalPkg @@ -807,5 +801,5 @@ func (s *session) gc() { // or (session)handleLoop automatically. It's thread safe. func (s *session) Close() { s.stop() - log.Info("%s closed now. its current gr num is %d", s.sessionToken(), atomic.LoadInt32(&(s.grNum))) + log.Infof("%s closed now. its current gr num is %d", s.sessionToken(), atomic.LoadInt32(&(s.grNum))) } diff --git a/utils.go b/utils.go new file mode 100644 index 00000000..4f16491f --- /dev/null +++ b/utils.go @@ -0,0 +1,196 @@ +package getty + +import ( + "net" + "strings" + "context" + "sync" + "time" +) + +// refers from https://github.com/facebookgo/grace/blob/master/gracenet/net.go#L180:6 +func IsSameAddr(a1, a2 net.Addr) bool { + if a1.Network() != a2.Network() { + return false + } + a1s := a1.String() + a2s := a2.String() + if a1s == a2s { + return true + } + + // This allows for ipv6 vs ipv4 local addresses to compare as equal. This + // scenario is common when listening on localhost. + const ipv6prefix = "[::]" + a1s = strings.TrimPrefix(a1s, ipv6prefix) + a2s = strings.TrimPrefix(a2s, ipv6prefix) + const ipv4prefix = "0.0.0.0" + a1s = strings.TrimPrefix(a1s, ipv4prefix) + a2s = strings.TrimPrefix(a2s, ipv4prefix) + return a1s == a2s +} + + +var ( + defaultCtxKey int = 1 +) + +type Values struct { + m map[interface{}]interface{} +} + +func (v Values) Get(key interface{}) (interface{}, bool) { + i, b := v.m[key] + return i, b +} + +func (c Values) Set(key interface{}, value interface{}) { + c.m[key] = value +} + +func (c Values) Delete(key interface{}) { + delete(c.m, key) +} + +type ValuesContext struct { + context.Context +} + +func NewValuesContext(ctx context.Context) *ValuesContext { + if ctx == nil { + ctx = context.Background() + } + + return &ValuesContext{ + Context: context.WithValue( + ctx, + defaultCtxKey, + Values{m: make(map[interface{}]interface{})}, + ), + } +} + +func (c *ValuesContext) Get(key interface{}) (interface{}, bool) { + return c.Context.Value(defaultCtxKey).(Values).Get(key) +} + +func (c *ValuesContext) Delete(key interface{}) { + c.Context.Value(defaultCtxKey).(Values).Delete(key) +} + +func (c *ValuesContext) Set(key interface{}, value interface{}) { + c.Context.Value(defaultCtxKey).(Values).Set(key, value) +} + + +type Wheel struct { + sync.RWMutex + span time.Duration + period time.Duration + ticker *time.Ticker + index int + ring []chan struct{} + once sync.Once + now time.Time +} + +func NewWheel(span time.Duration, buckets int) *Wheel { + var ( + w *Wheel + ) + + if span == 0 { + panic("@span == 0") + } + if buckets == 0 { + panic("@bucket == 0") + } + + w = &Wheel{ + span: span, + period: span * (time.Duration(buckets)), + ticker: time.NewTicker(span), + index: 0, + ring: make([](chan struct{}), buckets), + now: time.Now(), + } + + go func() { + var notify chan struct{} + // var cw CountWatch + // cw.Start() + for t := range w.ticker.C { + w.Lock() + w.now = t + + // fmt.Println("index:", w.index, ", value:", w.bitmap.Get(w.index)) + notify = w.ring[w.index] + w.ring[w.index] = nil + w.index = (w.index + 1) % len(w.ring) + + w.Unlock() + + if notify != nil { + close(notify) + } + } + // fmt.Println("timer costs:", cw.Count()/1e9, "s") + }() + + return w +} + +func (w *Wheel) Stop() { + w.once.Do(func() { w.ticker.Stop() }) +} + +func (w *Wheel) After(timeout time.Duration) <-chan struct{} { + if timeout >= w.period { + panic("@timeout over ring's life period") + } + + var pos = int(timeout / w.span) + if 0 < pos { + pos-- + } + + w.Lock() + pos = (w.index + pos) % len(w.ring) + if w.ring[pos] == nil { + w.ring[pos] = make(chan struct{}) + } + // fmt.Println("pos:", pos) + c := w.ring[pos] + w.Unlock() + + return c +} + +func (w *Wheel) Now() time.Time { + w.RLock() + now := w.now + w.RUnlock() + + return now +} + + + +type CountWatch struct { + start time.Time +} + +func (w *CountWatch) Start() { + var t time.Time + if t.Equal(w.start) { + w.start = time.Now() + } +} + +func (w *CountWatch) Reset() { + w.start = time.Now() +} + +func (w *CountWatch) Count() int64 { + return time.Since(w.start).Nanoseconds() +}