spectator/writer/unixgram_writer.go (47 lines of code) (raw):

package writer import ( "github.com/Netflix/spectator-go/v2/spectator/logger" "net" "strings" ) type UnixgramWriter struct { addr *net.UnixAddr conn *net.UnixConn logger logger.Logger } func NewUnixgramWriter(path string, logger logger.Logger) (*UnixgramWriter, error) { addr := &net.UnixAddr{Name: path, Net: "unixgram"} conn, err := net.DialUnix("unixgram", nil, addr) if err != nil { logger.Errorf("failed to dial unix socket: %v", err) conn = nil } return &UnixgramWriter{addr, conn, logger}, nil } // If anything disturbs access to the unix socket, such as a spectatord process restart (or another // unknown condition), then all future writes to the unix socket will fail with a "transport endpoint // is not connected" error. // // This means that the UdpWriter is generally more resilient across more operating conditions than the // UnixgramWriter. The UdpWriter does not continue to fail once it encounters a single failure to write, // it resumes writing when the port is available again, and it does not require any special connection // handling. // // The addition of reconnect logic to the UnixgramWriter mitigates ongoing issues with unix socket write // errors. Some packet delivery failure will occur until it can reconnect. With the reconnect logic in // place, the initialization is now more resilient if the unix socket is not available at program start. func (u *UnixgramWriter) Write(line string) { u.logger.Debugf("Sending line: %s", line) if u.conn != nil { if _, err := u.conn.Write([]byte(line)); err != nil { u.logger.Errorf("failed to write to unix socket: %v\n", err) if strings.Contains(err.Error(), "transport endpoint is not connected") { u.logger.Infof("close unix socket") err := u.conn.Close() if err != nil { u.logger.Errorf("failed to close unix socket: %v\n", err) } u.conn = nil } } } else { u.logger.Infof("re-dial unix socket") conn, err := net.DialUnix("unixgram", nil, u.addr) if err != nil { u.logger.Errorf("failed to dial unix socket: %v", err) } else { u.conn = conn } } } func (u *UnixgramWriter) Close() error { return u.conn.Close() }