github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/metrics/syslog_listener.go (about) 1 package metrics 2 3 import ( 4 "errors" 5 "net" 6 7 "github.com/golang/glog" 8 9 "github.com/nginxinc/kubernetes-ingress/internal/metrics/collectors" 10 ) 11 12 // SyslogListener is an interface for syslog metrics listener 13 // that reads syslog metrics logged by nginx 14 type SyslogListener interface { 15 Run() 16 Stop() 17 } 18 19 // LatencyMetricsListener implements the SyslogListener interface 20 type LatencyMetricsListener struct { 21 conn *net.UnixConn 22 addr string 23 collector collectors.LatencyCollector 24 } 25 26 // NewLatencyMetricsListener returns a LatencyMetricsListener that listens over a unix socket 27 // for syslog messages from nginx. 28 func NewLatencyMetricsListener(sockPath string, c collectors.LatencyCollector) SyslogListener { 29 glog.Infof("Starting latency metrics server listening on: %s", sockPath) 30 conn, err := net.ListenUnixgram("unixgram", &net.UnixAddr{ 31 Name: sockPath, 32 Net: "unixgram", 33 }) 34 if err != nil { 35 glog.Errorf("Failed to create latency metrics listener: %v. Latency metrics will not be collected.", err) 36 return NewSyslogFakeServer() 37 } 38 return &LatencyMetricsListener{conn: conn, addr: sockPath, collector: c} 39 } 40 41 // Run reads from the unix connection until an unrecoverable error occurs or the connection is closed. 42 func (l LatencyMetricsListener) Run() { 43 buffer := make([]byte, 1024) 44 for { 45 n, err := l.conn.Read(buffer) 46 if err != nil { 47 if !isErrorRecoverable(err) { 48 glog.Info("Stopping latency metrics listener") 49 return 50 } 51 } 52 go l.collector.RecordLatency(string(buffer[:n])) 53 } 54 } 55 56 // Stop closes the unix connection of the listener. 57 func (l LatencyMetricsListener) Stop() { 58 err := l.conn.Close() 59 if err != nil { 60 glog.Errorf("error closing latency metrics unix connection: %v", err) 61 } 62 } 63 64 func isErrorRecoverable(err error) bool { 65 var nerr *net.OpError 66 if errors.As(err, &nerr) && nerr.Temporary() { 67 return true 68 } else { 69 return false 70 } 71 } 72 73 // SyslogFakeListener is a fake implementation of the SyslogListener interface 74 type SyslogFakeListener struct{} 75 76 // NewFakeSyslogServer returns a SyslogFakeListener 77 func NewSyslogFakeServer() *SyslogFakeListener { 78 return &SyslogFakeListener{} 79 } 80 81 // Run is a fake implementation of SyslogListener Run 82 func (s SyslogFakeListener) Run() {} 83 84 // Stop is a fake implementation of SyslogListener Stop 85 func (s SyslogFakeListener) Stop() {}