github.com/netdata/go.d.plugin@v0.58.1/modules/wireguard/collect.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package wireguard 4 5 import ( 6 "fmt" 7 "time" 8 9 "golang.zx2c4.com/wireguard/wgctrl/wgtypes" 10 ) 11 12 func (w *WireGuard) collect() (map[string]int64, error) { 13 if w.client == nil { 14 client, err := w.newWGClient() 15 if err != nil { 16 return nil, fmt.Errorf("creating WireGuard client: %v", err) 17 } 18 w.client = client 19 } 20 21 // TODO: probably we need to get a list of interfaces and query interfaces using client.Device() 22 // https://github.com/WireGuard/wgctrl-go/blob/3d4a969bb56bb6931f6661af606bc9c4195b4249/internal/wglinux/client_linux.go#L79-L80 23 devices, err := w.client.Devices() 24 if err != nil { 25 return nil, fmt.Errorf("retrieving WireGuard devices: %v", err) 26 } 27 28 if len(devices) == 0 { 29 w.Info("no WireGuard devices found on the host system") 30 } 31 32 now := time.Now() 33 if w.cleanupLastTime.IsZero() { 34 w.cleanupLastTime = now 35 } 36 37 mx := make(map[string]int64) 38 39 w.collectDevicesPeers(mx, devices, now) 40 41 if now.Sub(w.cleanupLastTime) > w.cleanupEvery { 42 w.cleanupLastTime = now 43 w.cleanupDevicesPeers(devices) 44 } 45 46 return mx, nil 47 } 48 49 func (w *WireGuard) collectDevicesPeers(mx map[string]int64, devices []*wgtypes.Device, now time.Time) { 50 for _, d := range devices { 51 if !w.devices[d.Name] { 52 w.devices[d.Name] = true 53 w.addNewDeviceCharts(d.Name) 54 } 55 56 mx["device_"+d.Name+"_peers"] = int64(len(d.Peers)) 57 if len(d.Peers) == 0 { 58 mx["device_"+d.Name+"_receive"] = 0 59 mx["device_"+d.Name+"_transmit"] = 0 60 continue 61 } 62 63 for _, p := range d.Peers { 64 if p.LastHandshakeTime.IsZero() { 65 continue 66 } 67 68 pubKey := p.PublicKey.String() 69 id := peerID(d.Name, pubKey) 70 71 if !w.peers[id] { 72 w.peers[id] = true 73 w.addNewPeerCharts(id, d.Name, pubKey) 74 } 75 76 mx["device_"+d.Name+"_receive"] += p.ReceiveBytes 77 mx["device_"+d.Name+"_transmit"] += p.TransmitBytes 78 mx["peer_"+id+"_receive"] = p.ReceiveBytes 79 mx["peer_"+id+"_transmit"] = p.TransmitBytes 80 mx["peer_"+id+"_latest_handshake_ago"] = int64(now.Sub(p.LastHandshakeTime).Seconds()) 81 } 82 } 83 } 84 85 func (w *WireGuard) cleanupDevicesPeers(devices []*wgtypes.Device) { 86 seenDevices, seenPeers := make(map[string]bool), make(map[string]bool) 87 for _, d := range devices { 88 seenDevices[d.Name] = true 89 for _, p := range d.Peers { 90 seenPeers[peerID(d.Name, p.PublicKey.String())] = true 91 } 92 } 93 for d := range w.devices { 94 if !seenDevices[d] { 95 delete(w.devices, d) 96 w.removeDeviceCharts(d) 97 } 98 } 99 for p := range w.peers { 100 if !seenPeers[p] { 101 delete(w.peers, p) 102 w.removePeerCharts(p) 103 } 104 } 105 } 106 107 func peerID(device, peerPublicKey string) string { 108 return device + "_" + peerPublicKey 109 }