Mirror of my ganglia query CLI tool
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

140 lines
2.8 KiB

/*
*
*/
package main
import (
"net"
"fmt"
"os"
"io"
"sort"
"bufio"
"strings"
"strconv"
"encoding/xml"
)
type GangliaXML struct {
Cluster Cluster `xml:"CLUSTER"`
}
type Cluster struct {
Name string `xml:"NAME,attr"`
Hosts []Host `xml:"HOST"`
}
type Host struct {
Name string `xml:"NAME,attr"`
Ip string `xml:"IP,attr"`
Time int64 `xml:"REPORTED,attr"`
StartTime int64 `xml:"GMOND_STARTED,attr"`
Metrics []Metric `xml:"METRIC"`
}
type Metric struct {
Name string `xml:"NAME,attr"`
Value string `xml:"VAL,attr"`
Unit string `xml:"UNITS,attr"`
}
func HostRow(host Host) string {
cpu := -1.0
mem_tot := 0.0
mem_free := 0.0
// Get relevant metrics
for _, metric := range host.Metrics {
if metric.Name == "cpu_idle" {
cpu, _ = strconv.ParseFloat(metric.Value, 32)
cpu = 100 - cpu
}
if metric.Name == "mem_free" {
mem_free, _ = strconv.ParseFloat(metric.Value, 32)
}
if metric.Name == "mem_total" {
mem_tot, _ = strconv.ParseFloat(metric.Value, 32)
}
}
mem := -1.0
if mem_tot > 0 && mem_free > 0 {
mem = mem_tot/mem_free
}
return fmt.Sprintf("%20s\t%15s\t%12d%5.0f %%\t%5.0f %%", host.Name, host.Ip, host.Time, cpu, mem)
}
func readStream(reader io.Reader) ([]byte, error) {
data := make([]byte, 0)
buf := make([]byte, 2048)
for {
n, err := reader.Read(buf)
if err != nil {
if err == io.EOF {
break
} else {
return data, err
}
}
if n == 0 {
break
} else {
data = append(data, buf[:n]...)
}
}
return data, nil
}
func toUTF8(data []byte) []byte {
str := string(data)
str = strings.Replace(str, "ISO-8859-1", "UTF-8", 1)
return []byte(str)
}
func main() {
args := os.Args
port := 8649
if len(args) < 2 {
fmt.Printf("Usage: %s REMOTE [PORT]\n REMOTE is a ganglia server\n PORT defines the port to query (default: %d)\n", args[0], port)
return
}
remote := args[1] + ":" + strconv.Itoa(port)
conn, err := net.Dial("tcp", remote)
if err != nil {
fmt.Fprintln(os.Stderr, "Connection error: ", err)
os.Exit(1)
}
defer conn.Close()
// Read from conn
data, err := readStream(bufio.NewReader(conn))
if err != nil {
fmt.Fprintln(os.Stderr, "Error reading file: \n", err)
os.Exit(1)
}
// Hack: Replace "ISO-8859-1" to "UTF-8" in order to make it work with XML
data = toUTF8(data)
// Parse XML
var ganglia GangliaXML
if err := xml.Unmarshal(data, &ganglia); err != nil {
fmt.Fprintln(os.Stderr, "Error parsing xml: ", err)
return
}
fmt.Printf("Cluster: %s\n", ganglia.Cluster.Name);
hosts := ganglia.Cluster.Hosts
sort.Slice(hosts, func(i, j int) bool { return strings.Compare(hosts[i].Name, hosts[j].Name) < 0 })
// Header
fmt.Printf("%20s\t%15s\t%12s%7s\t%7s\n", "Host", "Ip", "Time", "CPU", "Memory")
for _, host := range hosts {
fmt.Printf("%s\n", HostRow(host))
}
}