mirror of
https://github.com/prometheus/node_exporter.git
synced 2024-12-22 16:36:07 +01:00
33f99c4fc1
Uses godep to vendor dependencies. Godeps is not necessary during build, golang's new vendor support is used instead.
225 lines
5.3 KiB
Go
225 lines
5.3 KiB
Go
package procfs
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"net"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// IPVSStats holds IPVS statistics, as exposed by the kernel in `/proc/net/ip_vs_stats`.
|
|
type IPVSStats struct {
|
|
// Total count of connections.
|
|
Connections uint64
|
|
// Total incoming packages processed.
|
|
IncomingPackets uint64
|
|
// Total outgoing packages processed.
|
|
OutgoingPackets uint64
|
|
// Total incoming traffic.
|
|
IncomingBytes uint64
|
|
// Total outgoing traffic.
|
|
OutgoingBytes uint64
|
|
}
|
|
|
|
// IPVSBackendStatus holds current metrics of one virtual / real address pair.
|
|
type IPVSBackendStatus struct {
|
|
// The local (virtual) IP address.
|
|
LocalAddress net.IP
|
|
// The local (virtual) port.
|
|
LocalPort uint16
|
|
// The transport protocol (TCP, UDP).
|
|
Proto string
|
|
// The remote (real) IP address.
|
|
RemoteAddress net.IP
|
|
// The remote (real) port.
|
|
RemotePort uint16
|
|
// The current number of active connections for this virtual/real address pair.
|
|
ActiveConn uint64
|
|
// The current number of inactive connections for this virtual/real address pair.
|
|
InactConn uint64
|
|
// The current weight of this virtual/real address pair.
|
|
Weight uint64
|
|
}
|
|
|
|
// NewIPVSStats reads the IPVS statistics.
|
|
func NewIPVSStats() (IPVSStats, error) {
|
|
fs, err := NewFS(DefaultMountPoint)
|
|
if err != nil {
|
|
return IPVSStats{}, err
|
|
}
|
|
|
|
return fs.NewIPVSStats()
|
|
}
|
|
|
|
// NewIPVSStats reads the IPVS statistics from the specified `proc` filesystem.
|
|
func (fs FS) NewIPVSStats() (IPVSStats, error) {
|
|
file, err := os.Open(fs.Path("net/ip_vs_stats"))
|
|
if err != nil {
|
|
return IPVSStats{}, err
|
|
}
|
|
defer file.Close()
|
|
|
|
return parseIPVSStats(file)
|
|
}
|
|
|
|
// parseIPVSStats performs the actual parsing of `ip_vs_stats`.
|
|
func parseIPVSStats(file io.Reader) (IPVSStats, error) {
|
|
var (
|
|
statContent []byte
|
|
statLines []string
|
|
statFields []string
|
|
stats IPVSStats
|
|
)
|
|
|
|
statContent, err := ioutil.ReadAll(file)
|
|
if err != nil {
|
|
return IPVSStats{}, err
|
|
}
|
|
|
|
statLines = strings.SplitN(string(statContent), "\n", 4)
|
|
if len(statLines) != 4 {
|
|
return IPVSStats{}, errors.New("ip_vs_stats corrupt: too short")
|
|
}
|
|
|
|
statFields = strings.Fields(statLines[2])
|
|
if len(statFields) != 5 {
|
|
return IPVSStats{}, errors.New("ip_vs_stats corrupt: unexpected number of fields")
|
|
}
|
|
|
|
stats.Connections, err = strconv.ParseUint(statFields[0], 16, 64)
|
|
if err != nil {
|
|
return IPVSStats{}, err
|
|
}
|
|
stats.IncomingPackets, err = strconv.ParseUint(statFields[1], 16, 64)
|
|
if err != nil {
|
|
return IPVSStats{}, err
|
|
}
|
|
stats.OutgoingPackets, err = strconv.ParseUint(statFields[2], 16, 64)
|
|
if err != nil {
|
|
return IPVSStats{}, err
|
|
}
|
|
stats.IncomingBytes, err = strconv.ParseUint(statFields[3], 16, 64)
|
|
if err != nil {
|
|
return IPVSStats{}, err
|
|
}
|
|
stats.OutgoingBytes, err = strconv.ParseUint(statFields[4], 16, 64)
|
|
if err != nil {
|
|
return IPVSStats{}, err
|
|
}
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs.
|
|
func NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
|
|
fs, err := NewFS(DefaultMountPoint)
|
|
if err != nil {
|
|
return []IPVSBackendStatus{}, err
|
|
}
|
|
|
|
return fs.NewIPVSBackendStatus()
|
|
}
|
|
|
|
// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem.
|
|
func (fs FS) NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
|
|
file, err := os.Open(fs.Path("net/ip_vs"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
return parseIPVSBackendStatus(file)
|
|
}
|
|
|
|
func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) {
|
|
var (
|
|
status []IPVSBackendStatus
|
|
scanner = bufio.NewScanner(file)
|
|
proto string
|
|
localAddress net.IP
|
|
localPort uint16
|
|
err error
|
|
)
|
|
|
|
for scanner.Scan() {
|
|
fields := strings.Fields(string(scanner.Text()))
|
|
if len(fields) == 0 {
|
|
continue
|
|
}
|
|
switch {
|
|
case fields[0] == "IP" || fields[0] == "Prot" || fields[1] == "RemoteAddress:Port":
|
|
continue
|
|
case fields[0] == "TCP" || fields[0] == "UDP":
|
|
if len(fields) < 2 {
|
|
continue
|
|
}
|
|
proto = fields[0]
|
|
localAddress, localPort, err = parseIPPort(fields[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
case fields[0] == "->":
|
|
if len(fields) < 6 {
|
|
continue
|
|
}
|
|
remoteAddress, remotePort, err := parseIPPort(fields[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
weight, err := strconv.ParseUint(fields[3], 10, 64)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
activeConn, err := strconv.ParseUint(fields[4], 10, 64)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
inactConn, err := strconv.ParseUint(fields[5], 10, 64)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
status = append(status, IPVSBackendStatus{
|
|
LocalAddress: localAddress,
|
|
LocalPort: localPort,
|
|
RemoteAddress: remoteAddress,
|
|
RemotePort: remotePort,
|
|
Proto: proto,
|
|
Weight: weight,
|
|
ActiveConn: activeConn,
|
|
InactConn: inactConn,
|
|
})
|
|
}
|
|
}
|
|
return status, nil
|
|
}
|
|
|
|
func parseIPPort(s string) (net.IP, uint16, error) {
|
|
tmp := strings.SplitN(s, ":", 2)
|
|
|
|
if len(tmp) != 2 {
|
|
return nil, 0, fmt.Errorf("invalid IP:Port: %s", s)
|
|
}
|
|
|
|
if len(tmp[0]) != 8 && len(tmp[0]) != 32 {
|
|
return nil, 0, fmt.Errorf("invalid IP: %s", tmp[0])
|
|
}
|
|
|
|
ip, err := hex.DecodeString(tmp[0])
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
port, err := strconv.ParseUint(tmp[1], 16, 16)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return ip, uint16(port), nil
|
|
}
|