diff --git a/recws.go b/recws.go index 5bd82b1..72af942 100644 --- a/recws.go +++ b/recws.go @@ -5,6 +5,7 @@ package recws import ( "crypto/tls" "errors" + "fmt" "log" "math/rand" "net/http" @@ -44,6 +45,8 @@ type RecConn struct { // KeepAliveTimeout is an interval for sending ping/pong messages // disabled if 0 KeepAliveTimeout time.Duration + // LogHandler handles all log messages + LogHandler func(v LogValues) // NonVerbose suppress connecting/reconnecting messages. NonVerbose bool @@ -58,6 +61,18 @@ type RecConn struct { *websocket.Conn } +// LogValues type includes values for send to logger +type LogValues struct { + // Msg is main message + Msg string + // Err is error for separate and display it + Err error + // Url is connection url + Url string + // Fatal is tag of fatal error + Fatal bool +} + // CloseAndReconnect will try to reconnect. func (rc *RecConn) CloseAndReconnect() { rc.Close() @@ -97,7 +112,7 @@ func (rc *RecConn) Shutdown(writeWait time.Duration) { err := rc.WriteControl(websocket.CloseMessage, msg, time.Now().Add(writeWait)) if err != nil && err != websocket.ErrCloseSent { // If close message could not be sent, then close without the handshake. - log.Printf("Shutdown: %v", err) + rc.log(LogValues{Err: err, Msg: "Shutdown"}) rc.Close() } } @@ -314,7 +329,7 @@ func (rc *RecConn) Dial(urlStr string, reqHeader http.Header) { urlStr, err := rc.parseURL(urlStr) if err != nil { - log.Fatalf("Dial: %v", err) + rc.log(LogValues{Msg: "Dial", Err: err, Fatal: true}) } // Config @@ -342,6 +357,16 @@ func (rc *RecConn) GetURL() string { return rc.url } +func (rc *RecConn) log(v LogValues) { + if rc.LogHandler != nil { + rc.LogHandler(v) + } else if v.Err != nil { + log.Printf("ERROR: %+v: %+v (%+v)\n", v.Msg, v.Err, v.Url) + } else { + log.Printf("%+v (%+v)\n", v.Msg, v.Url) + } +} + func (rc *RecConn) getNonVerbose() bool { rc.mu.RLock() defer rc.mu.RUnlock() @@ -404,12 +429,13 @@ func (rc *RecConn) keepAlive() { } if err := rc.writeControlPingMessage(); err != nil { - log.Println(err) + rc.log(LogValues{Err: err}) } <-ticker.C timeoutOffset := time.Millisecond * 500 if time.Since(keepAliveResponse.getLastResponse()) > rc.getKeepAliveTimeout()+timeoutOffset { + rc.log(LogValues{Err: errors.New("keepalive timeout"), Msg: "Reconnect", Url: rc.url}) rc.CloseAndReconnect() return } @@ -434,15 +460,15 @@ func (rc *RecConn) connect() { if err == nil { if !rc.getNonVerbose() { - log.Printf("Dial: connection was successfully established with %s\n", rc.url) + rc.log(LogValues{Msg: "Dial: connection was successfully established", Url: rc.url}) } if rc.hasSubscribeHandler() { if err := rc.SubscribeHandler(); err != nil { - log.Fatalf("Dial: connect handler failed with %s", err.Error()) + rc.log(LogValues{Msg: "Dial: connect handler failed", Err: err, Fatal: true}) } if !rc.getNonVerbose() { - log.Printf("Dial: connect handler was successfully established with %s\n", rc.url) + rc.log(LogValues{Msg: "Dial: connect handler was successfully established with %s", Url: rc.url}) } } @@ -454,8 +480,7 @@ func (rc *RecConn) connect() { } if !rc.getNonVerbose() { - log.Println(err) - log.Println("Dial: will try again in", nextItvl, "seconds.") + rc.log(LogValues{Err: err, Msg: fmt.Sprintf("Dial: will try again in %+v seconds", nextItvl)}) } time.Sleep(nextItvl)