133 lines
3.4 KiB
Go
133 lines
3.4 KiB
Go
package collector
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type HAProxyInfo struct {
|
|
Uptime string `json:"uptime"`
|
|
CurrentConns int `json:"current_conns"`
|
|
TotalConns int `json:"total_conns"`
|
|
TotalReqs int `json:"total_requests"`
|
|
CurrentSSL int `json:"current_ssl"`
|
|
TotalSSL int `json:"total_ssl"`
|
|
MaxConns int `json:"max_conns"`
|
|
}
|
|
|
|
type HAProxyEntry struct {
|
|
ProxyName string `json:"proxy_name"`
|
|
ServerName string `json:"server_name"`
|
|
Type string `json:"type"`
|
|
Status string `json:"status"`
|
|
CurrentSessions int `json:"current_sessions"`
|
|
TotalSessions int `json:"total_sessions"`
|
|
BytesIn int64 `json:"bytes_in"`
|
|
BytesOut int64 `json:"bytes_out"`
|
|
RequestsTotal int `json:"requests_total"`
|
|
ErrorsReq int `json:"errors_req"`
|
|
ErrorsConn int `json:"errors_conn"`
|
|
ErrorsResp int `json:"errors_resp"`
|
|
}
|
|
|
|
type HAProxyData struct {
|
|
Info HAProxyInfo `json:"info"`
|
|
Entries []HAProxyEntry `json:"entries"`
|
|
}
|
|
|
|
const haproxySocket = "/var/run/haproxy.socket"
|
|
|
|
func CollectHAProxy() *HAProxyData {
|
|
if _, err := os.Stat(haproxySocket); err != nil {
|
|
return nil
|
|
}
|
|
|
|
data := &HAProxyData{}
|
|
|
|
// show info
|
|
if out, err := exec.Command("/bin/sh", "-c", `echo "show info" | /usr/bin/nc -U `+haproxySocket).Output(); err == nil {
|
|
info := parseHAProxyInfo(string(out))
|
|
data.Info = info
|
|
}
|
|
|
|
// show stat
|
|
if out, err := exec.Command("/bin/sh", "-c", `echo "show stat" | /usr/bin/nc -U `+haproxySocket).Output(); err == nil {
|
|
data.Entries = parseHAProxyStats(string(out))
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
func parseHAProxyInfo(output string) HAProxyInfo {
|
|
info := HAProxyInfo{}
|
|
for _, line := range strings.Split(output, "\n") {
|
|
parts := strings.SplitN(line, ":", 2)
|
|
if len(parts) != 2 {
|
|
continue
|
|
}
|
|
key := strings.TrimSpace(parts[0])
|
|
val := strings.TrimSpace(parts[1])
|
|
switch key {
|
|
case "Uptime":
|
|
info.Uptime = val
|
|
case "CurrConns":
|
|
info.CurrentConns, _ = strconv.Atoi(val)
|
|
case "CumConns":
|
|
info.TotalConns, _ = strconv.Atoi(val)
|
|
case "CumReq":
|
|
info.TotalReqs, _ = strconv.Atoi(val)
|
|
case "CurrSslConns":
|
|
info.CurrentSSL, _ = strconv.Atoi(val)
|
|
case "CumSslConns":
|
|
info.TotalSSL, _ = strconv.Atoi(val)
|
|
case "Maxconn":
|
|
info.MaxConns, _ = strconv.Atoi(val)
|
|
}
|
|
}
|
|
return info
|
|
}
|
|
|
|
func parseHAProxyStats(output string) []HAProxyEntry {
|
|
var entries []HAProxyEntry
|
|
lines := strings.Split(output, "\n")
|
|
for _, line := range lines {
|
|
if strings.HasPrefix(line, "#") || strings.TrimSpace(line) == "" {
|
|
continue
|
|
}
|
|
fields := strings.Split(line, ",")
|
|
if len(fields) < 18 {
|
|
continue
|
|
}
|
|
|
|
svname := fields[1]
|
|
entryType := "server"
|
|
if svname == "FRONTEND" {
|
|
entryType = "frontend"
|
|
} else if svname == "BACKEND" {
|
|
entryType = "backend"
|
|
}
|
|
|
|
e := HAProxyEntry{
|
|
ProxyName: fields[0],
|
|
ServerName: svname,
|
|
Type: entryType,
|
|
Status: fields[17],
|
|
}
|
|
e.CurrentSessions, _ = strconv.Atoi(fields[4])
|
|
e.TotalSessions, _ = strconv.Atoi(fields[7])
|
|
e.BytesIn, _ = strconv.ParseInt(fields[8], 10, 64)
|
|
e.BytesOut, _ = strconv.ParseInt(fields[9], 10, 64)
|
|
e.ErrorsReq, _ = strconv.Atoi(fields[12])
|
|
e.ErrorsConn, _ = strconv.Atoi(fields[13])
|
|
e.ErrorsResp, _ = strconv.Atoi(fields[14])
|
|
if len(fields) > 48 {
|
|
e.RequestsTotal, _ = strconv.Atoi(fields[48])
|
|
}
|
|
|
|
entries = append(entries, e)
|
|
}
|
|
return entries
|
|
}
|