github.com/sujit-baniya/log@v1.0.73/gelf/tcpwriter.go (about) 1 package gelf 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "sync" 8 "time" 9 ) 10 11 const ( 12 DefaultMaxReconnect = 3 13 DefaultReconnectDelay = 1 14 ) 15 16 type TCPWriter struct { 17 Writer 18 mu sync.Mutex 19 MaxReconnect int 20 ReconnectDelay time.Duration 21 } 22 23 func NewTCPWriter(addr string) (*TCPWriter, error) { 24 var err error 25 w := new(TCPWriter) 26 w.MaxReconnect = DefaultMaxReconnect 27 w.ReconnectDelay = DefaultReconnectDelay 28 w.proto = "tcp" 29 w.addr = addr 30 31 if w.conn, err = net.Dial("tcp", addr); err != nil { 32 return nil, err 33 } 34 if w.hostname, err = os.Hostname(); err != nil { 35 return nil, err 36 } 37 38 return w, nil 39 } 40 41 // WriteMessage sends the specified message to the GELF server 42 // specified in the call to New(). It assumes all the fields are 43 // filled out appropriately. In general, clients will want to use 44 // Write, rather than WriteMessage. 45 func (w *TCPWriter) WriteMessage(m *Message) (err error) { 46 buf := newBuffer() 47 defer bufPool.Put(buf) 48 messageBytes, err := m.toBytes(buf) 49 if err != nil { 50 return err 51 } 52 53 messageBytes = append(messageBytes, 0) 54 55 n, err := w.writeToSocketWithReconnectAttempts(messageBytes) 56 if err != nil { 57 return err 58 } 59 if n != len(messageBytes) { 60 return fmt.Errorf("bad write (%d/%d)", n, len(messageBytes)) 61 } 62 63 return nil 64 } 65 66 func (w *TCPWriter) Write(p []byte) (n int, err error) { 67 file, line := getCallerIgnoringLogMulti(1) 68 69 m := constructMessage(p, w.hostname, w.Facility, file, line) 70 71 if err = w.WriteMessage(m); err != nil { 72 return 0, err 73 } 74 75 return len(p), nil 76 } 77 78 func (w *TCPWriter) writeToSocketWithReconnectAttempts(zBytes []byte) (n int, err error) { 79 var errConn error 80 var i int 81 82 w.mu.Lock() 83 for i = 0; i <= w.MaxReconnect; i++ { 84 errConn = nil 85 86 if w.conn != nil { 87 n, err = w.conn.Write(zBytes) 88 } else { 89 err = fmt.Errorf("Connection was nil, will attempt reconnect") 90 } 91 if err != nil { 92 time.Sleep(w.ReconnectDelay * time.Second) 93 w.conn, errConn = net.Dial("tcp", w.addr) 94 } else { 95 break 96 } 97 } 98 w.mu.Unlock() 99 100 if i > w.MaxReconnect { 101 return 0, fmt.Errorf("Maximum reconnection attempts was reached; giving up") 102 } 103 if errConn != nil { 104 return 0, fmt.Errorf("Write Failed: %s\nReconnection failed: %s", err, errConn) 105 } 106 return n, nil 107 }