blob: 4fbda71270d3b3b52f8001fd794f1fb906839b1d [file] [log] [blame]
package profiler
import (
"fmt"
"strconv"
"strings"
"cos.googlesource.com/cos/tools.git/src/pkg/nodeprofiler/utils"
)
// Command interface defines functions that can be implemented by
// structs to execute shell commands.
type Command interface {
Name() string
Run() (map[string][]string, error)
}
// vmstat represents a vmstat command.
type vmstat struct {
name string
// delay specifies times between updates in seconds.
delay int
// count specifies number of updates.
count int
// titles specifies the titles to get values for.
titles []string
}
// Name returns the name for vmstat command.
func (v *vmstat) Name() string {
return v.name
}
func (v *vmstat) setDefaults() {
if v.delay == 0 {
v.delay = 1
}
if v.count == 0 {
v.count = 5
}
}
// Run executes the vmstat command, parses the output and returns it as
// a map of titles to their values.
func (v *vmstat) Run() (map[string][]string, error) {
// if delay and count not set
v.setDefaults()
interval := strconv.Itoa(v.delay)
count := strconv.Itoa(v.count)
out, err := utils.RunCommand(v.Name(), "-n", interval, count)
if err != nil {
return nil, fmt.Errorf("failed to run the command 'vmstat': %v", err)
}
s := string(out)
lines := strings.Split(strings.Trim(s, "\n"), "\n")
// ignore the first row in vmstat's output
lines = lines[1:]
titles := v.titles
// parse output by columns
output, err := utils.ParseColumns(lines, titles...)
return output, err
}
// lscpu represents an lscpu command.
type lscpu struct {
name string
// titles specifies the titles to get values for.
titles []string
}
// Name returns the name for the lscpu command.
func (l *lscpu) Name() string {
return l.name
}
// Run executes the lscpu command, parses the output and returns a
// a map of title(s) to their values.
func (l *lscpu) Run() (map[string][]string, error) {
out, err := utils.RunCommand(l.Name())
if err != nil {
return nil, fmt.Errorf("failed to run the command 'lscpu': %v", err)
}
s := string(out)
lines := strings.Split(strings.Trim(s, "\n"), "\n")
titles := l.titles
// parse output by rows
output, err := utils.ParseRows(lines, ":", titles...)
return output, err
}
// free represents a free command.
type free struct {
name string
// titles specifies the titles to get values for.
titles []string
}
// Name returns the name for the free command.
func (f *free) Name() string {
return f.name
}
// Run executes the free commands, parses the output and returns a
// a map of title(s) to their values.
func (f *free) Run() (map[string][]string, error) {
out, err := utils.RunCommand(f.Name(), "-m")
if err != nil {
return nil, fmt.Errorf("failed to run the command 'free': %v", err)
}
s := string(out)
lines := strings.Split(strings.Trim(s, "\n"), "\n")
titles := f.titles
// parse output by rows and columns
output, err := utils.ParseRowsAndColumns(lines, titles...)
return output, err
}
// iostat represents an iostat command
type iostat struct {
name string
// flags specify the flags to be passed into the command.
flags string
// delay specifies times between updates in seconds.
delay int
// count specifies number of updates.
count int
// titles specifies the titles to get values for.
titles []string
}
// Name returns the name for the iostat command.
func (i *iostat) Name() string {
return i.name
}
func (i *iostat) setDefaults() {
if i.delay == 0 {
i.delay = 1
}
if i.count == 0 {
i.count = 5
}
}
// Run executes the iostat commands, parses the output and returns a
// a map of title(s) to their values.
func (i *iostat) Run() (map[string][]string, error) {
// if delay and count not set
i.setDefaults()
interval := strconv.Itoa(i.delay)
count := strconv.Itoa(i.count)
out, err := utils.RunCommand(i.Name(), i.flags, interval, count)
if err != nil {
return nil, fmt.Errorf("failed to run the command 'iostat': %v", err)
}
s := string(out)
lines := strings.Split(strings.Trim(s, "\n"), "\n")
titles := i.titles
// ignore the first 2 lines in iostat's output so that the first line
// is column titles.
lines = lines[2:]
// parse output by rows and columns
output, err := utils.ParseColumns(lines, titles...)
return output, err
}