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() {}