add metrics for the udp sockets using SO_MEMINFO (#390)
Retrieve the current socket stats using SO_MEMINFO and report them as metrics gauges. If SO_MEMINFO isn't supported, we don't report these metrics.
This commit is contained in:
parent
ecfb40f29c
commit
d232ccbfab
|
@ -268,8 +268,13 @@ func (f *Interface) reloadFirewall(c *Config) {
|
||||||
|
|
||||||
func (f *Interface) emitStats(i time.Duration) {
|
func (f *Interface) emitStats(i time.Duration) {
|
||||||
ticker := time.NewTicker(i)
|
ticker := time.NewTicker(i)
|
||||||
|
|
||||||
|
udpStats := NewUDPStatsEmitter(f.writers)
|
||||||
|
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
f.firewall.EmitStats()
|
f.firewall.EmitStats()
|
||||||
f.handshakeManager.EmitStats()
|
f.handshakeManager.EmitStats()
|
||||||
|
|
||||||
|
udpStats()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,11 @@ func (u *udpConn) reloadConfig(c *Config) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewUDPStatsEmitter(udpConns []*udpConn) func() {
|
||||||
|
// No UDP stats for non-linux
|
||||||
|
return func() {}
|
||||||
|
}
|
||||||
|
|
||||||
type rawMessage struct {
|
type rawMessage struct {
|
||||||
Len uint32
|
Len uint32
|
||||||
}
|
}
|
||||||
|
|
59
udp_linux.go
59
udp_linux.go
|
@ -12,6 +12,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/rcrowley/go-metrics"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,6 +56,23 @@ type rawSockaddrAny struct {
|
||||||
|
|
||||||
var x int
|
var x int
|
||||||
|
|
||||||
|
// From linux/sock_diag.h
|
||||||
|
const (
|
||||||
|
_SK_MEMINFO_RMEM_ALLOC = iota
|
||||||
|
_SK_MEMINFO_RCVBUF
|
||||||
|
_SK_MEMINFO_WMEM_ALLOC
|
||||||
|
_SK_MEMINFO_SNDBUF
|
||||||
|
_SK_MEMINFO_FWD_ALLOC
|
||||||
|
_SK_MEMINFO_WMEM_QUEUED
|
||||||
|
_SK_MEMINFO_OPTMEM
|
||||||
|
_SK_MEMINFO_BACKLOG
|
||||||
|
_SK_MEMINFO_DROPS
|
||||||
|
|
||||||
|
_SK_MEMINFO_VARS
|
||||||
|
)
|
||||||
|
|
||||||
|
type _SK_MEMINFO [_SK_MEMINFO_VARS]uint32
|
||||||
|
|
||||||
func NewListener(ip string, port int, multi bool) (*udpConn, error) {
|
func NewListener(ip string, port int, multi bool) (*udpConn, error) {
|
||||||
syscall.ForkLock.RLock()
|
syscall.ForkLock.RLock()
|
||||||
fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_UDP)
|
fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_UDP)
|
||||||
|
@ -281,6 +299,47 @@ func (u *udpConn) reloadConfig(c *Config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *udpConn) getMemInfo(meminfo *_SK_MEMINFO) error {
|
||||||
|
var vallen uint32 = 4 * _SK_MEMINFO_VARS
|
||||||
|
_, _, err := unix.Syscall6(unix.SYS_GETSOCKOPT, uintptr(u.sysFd), uintptr(unix.SOL_SOCKET), uintptr(unix.SO_MEMINFO), uintptr(unsafe.Pointer(meminfo)), uintptr(unsafe.Pointer(&vallen)), 0)
|
||||||
|
if err != 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUDPStatsEmitter(udpConns []*udpConn) func() {
|
||||||
|
// Check if our kernel supports SO_MEMINFO before registering the gauges
|
||||||
|
var udpGauges [][_SK_MEMINFO_VARS]metrics.Gauge
|
||||||
|
var meminfo _SK_MEMINFO
|
||||||
|
if err := udpConns[0].getMemInfo(&meminfo); err == nil {
|
||||||
|
udpGauges = make([][_SK_MEMINFO_VARS]metrics.Gauge, len(udpConns))
|
||||||
|
for i := range udpConns {
|
||||||
|
udpGauges[i] = [_SK_MEMINFO_VARS]metrics.Gauge{
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.rmem_alloc", i), nil),
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.rcvbuf", i), nil),
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.wmem_alloc", i), nil),
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.sndbuf", i), nil),
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.fwd_alloc", i), nil),
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.wmem_queued", i), nil),
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.optmem", i), nil),
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.backlog", i), nil),
|
||||||
|
metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.drops", i), nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
for i, gauges := range udpGauges {
|
||||||
|
if err := udpConns[i].getMemInfo(&meminfo); err == nil {
|
||||||
|
for j := 0; j < _SK_MEMINFO_VARS; j++ {
|
||||||
|
gauges[j].Update(int64(meminfo[j]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (ua *udpAddr) Equals(t *udpAddr) bool {
|
func (ua *udpAddr) Equals(t *udpAddr) bool {
|
||||||
if t == nil || ua == nil {
|
if t == nil || ua == nil {
|
||||||
return t == nil && ua == nil
|
return t == nil && ua == nil
|
||||||
|
|
Loading…
Reference in New Issue