func ListContainers() ([]string, error) { out, err := linux.Exec("docker ps -q --no-trunc") if err != nil { return nil, err } return strings.Fields(out), nil }
func GetNetInUsage(cont string) (int64, error) { cmd := fmt.Sprintf("docker exec %s cat /sys/devices/virtual/net/eth0/statistics/rx_bytes", cont) out, err := linux.Exec(cmd) if err != nil { return 0, err } net, err := strconv.ParseInt(strings.TrimSpace(out), 10, 64) if err != nil { return 0, err } return net, nil }
func GetMemUsage(cont string) (int64, error) { cmd := fmt.Sprintf("head -2 /sys/fs/cgroup/memory/system.slice/docker-%s.scope/memory.stat", cont) out, err := linux.Exec(cmd) if err != nil { return 0, err } mem, err := strconv.ParseInt(strings.Fields(out)[3], 10, 64) if err != nil { return 0, err } return mem, nil }
func main() { // read arguments if len(os.Args) < 3 { fmt.Println("[ERROR] incomplete command!") fmt.Printf("Usage: %s <cont-name> <freq>\n", os.Args[0]) os.Exit(1) } cont_name := os.Args[1] freq, err := strconv.ParseInt(os.Args[2], 10, 32) if err != nil { fmt.Println("[ERROR] unknown frequency argument!") os.Exit(1) } // get container id out, err := linux.Exec(fmt.Sprintf("docker inspect --format='{{.Id}}' %s", cont_name)) if err != nil { fmt.Printf("[ERROR] unable to run cmd, output: (%s)\n", out) panic(err) } cont_id := strings.TrimSpace(string(out)) // check if feedgnuplot exists command := exec.Command("which", "feedgnuplot") empty, err := command.CombinedOutput() if err != nil || string(empty) == "" { panic("[ERROR] feedgnuplot doesn't exists!") } // CTRL+C signal handler sigs := make(chan os.Signal, 1) done := true signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) go func() { _ = <-sigs done = false }() // init feedgnuplot command = exec.Command("feedgnuplot", "--lines --stream --title 'cpu-usage' --ylabel 'cpu (100% = 1core)' --xlabel 'time ticks'") reader, writer := io.Pipe() command.Stdin = reader command.Stdout = os.Stdout command.Stderr = os.Stderr err = command.Start() if err != nil { fmt.Println("[ERROR] error while starting feedgnuplot!") panic(err) } // init readings cur_time := time.Now().UnixNano() cur_cpu, err := docker.GetCPUUsage(cont_id) if err != nil { fmt.Println("[WARN] unable to get container CPU usage!") cur_cpu = 0 } // infinite loop for plotting data for done { new_cpu, err := docker.GetCPUUsage(cont_id) if err != nil { fmt.Println("[WARN] unable to get container CPU usage!") new_cpu = 0 } new_time := time.Now().UnixNano() avg_cpu := float64(new_cpu-cur_cpu) / float64(new_time-cur_time) * 1000000000.0 cur_time = new_time cur_cpu = new_cpu _, err = io.WriteString(writer, fmt.Sprintf("%.6f\n", avg_cpu)) if err != nil { panic("[ERROR] unable to write to feedgnuplot-stdin!") } time.Sleep(time.Duration(freq) * time.Millisecond) } _, err = io.WriteString(writer, "exit\n") if err != nil { panic("[ERROR] unable to write to feedgnuplot-stdin!") } command.Wait() return }
func sendNetUsage(interval time.Duration) { out, err := linux.Exec("ifconfig -s") now := time.Now() if err != nil { log.Printf("[WARN] unable to get system net usage: ", err.Error()) } else { reader := csv.NewReader(strings.NewReader(out)) reader.Comma = ' ' reader.TrimLeadingSpace = true net_data, err := reader.ReadAll() if err != nil { log.Println("[WARN] unable to get system net usage: ", err.Error()) } else { for index, row := range net_data { if index == 0 { continue } net, err := strconv.ParseInt(row[3], 10, 64) if err != nil { log.Println("[WARN] error in converting to integer: ", err.Error()) } else { ntup, ok := rxdata[row[0]] if ok { avg := float64(net-ntup.net) * 1000000000 / float64(now.Sub(ntup.time)) ntup.time = now ntup.net = net dispatch(row[0], now, avg, "rx") } else { rxdata[row[0]] = &ntuple{time: now, net: net} } } net, err = strconv.ParseInt(row[7], 10, 64) if err != nil { log.Println("[WARN] error in converting to integer: ", err.Error()) } else { ntup, ok := txdata[row[0]] if ok { avg := float64(net-ntup.net) * 1000000000 / float64(now.Sub(ntup.time)) ntup.time = now ntup.net = net dispatch(row[0], now, avg, "tx") } else { txdata[row[0]] = &ntuple{time: now, net: net} } } } } } conts, err := docker.ListContainers() if err != nil { log.Fatalln("[WARN] unable to get list of containers: ", err.Error()) } for _, cont := range conts { net, err := docker.GetNetInUsage(cont) now = time.Now() if err != nil { log.Printf("[WARN] unable to get rx net usage for %s: %s\n", cont, err.Error()) } else { ntup, ok := rxdata[cont] if ok { avg := float64(net-ntup.net) * 1000000000 / float64(now.Sub(ntup.time)) ntup.time = now ntup.net = net dispatch(cont, now, avg, "rx") } else { rxdata[cont] = &ntuple{time: now, net: net} } } net, err = docker.GetNetOutUsage(cont) now = time.Now() if err != nil { log.Printf("[WARN] unable to get tx net usage for %s: %s\n", cont, err.Error()) } else { ntup, ok := txdata[cont] if ok { avg := float64(net-ntup.net) * 1000000000 / float64(now.Sub(ntup.time)) ntup.time = now ntup.net = net dispatch(cont, now, avg, "tx") } else { txdata[cont] = &ntuple{time: now, net: net} } } } for _, client := range clients { client.Flush() } }