Skip to content

Commit

Permalink
Feature/windows inspectors (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
deven96 authored Mar 19, 2022
1 parent faf3f84 commit bacd714
Show file tree
Hide file tree
Showing 12 changed files with 352 additions and 38 deletions.
2 changes: 1 addition & 1 deletion driver/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (d *SSH) GetDetails() SystemDetails {
uname, err := d.RunCommand(`uname`)
// try windows command
if err != nil {
windowsName, err := d.RunCommand(`systeminfo | findstr /B /C:"OS Name"`)
windowsName, err := d.RunCommand(`systeminfo | findstr /R /C:Windows`)
if err == nil {
if strings.Contains(strings.ToLower(windowsName), "windows") {
uname = "windows"
Expand Down
28 changes: 26 additions & 2 deletions inspector/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@ type DF struct {
}

// Parse : run custom parsing on output of the command
/*
For Darwin it looks something like
FileSystem 1024-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1s5 244679060 10984568 47579472 19% 488275 2446302325 0% /
devfs 220 220 0 100% 774 0 100% /dev
/dev/disk1s1 244679060 179090752 47579472 80% 1205263 2445585337 0% /System/Volumes/Data
/dev/disk1s4 244679060 6292564 47579472 12% 7 2446790593 0% /private/var/vm
map auto_home 0 0 0 100% 0 0 100% /System/Volumes/Data/home
For Linux it looks something like
Filesystem 1K-blocks Used Available Use% Mounted on
sysfs 0 0 0 - /sys
proc 0 0 0 - /proc
udev 8029020 0 8029020 0% /dev
devpts 0 0 0 - /dev/pts
tmpfs 1612500 2112 1610388 1% /run
*/
func (i *DF) Parse(output string) {
var values []DFMetrics
log.Debug("Parsing ouput string in DF inspector")
Expand Down Expand Up @@ -92,8 +112,7 @@ func (i *DF) Execute() {
}
}

// TODO: Implement DF for windows using
// `wmic logicaldisk` to satisfy Inspector interface
// DFWin: parse `wmic logicaldisk` to satisfy Inspector interface
type DFWin struct {
Driver *driver.Driver
Command string
Expand All @@ -107,6 +126,11 @@ type DFWin struct {
Values []DFMetrics
}

/* Parse : For the following windows output
Node,DeviceID,DriveType,FreeSpace,ProviderName,Size,VolumeName
IMANI,C:,3,191980253184,,288303964160,OS
*/
func (i *DFWin) Parse(output string) {
var values []DFMetrics
log.Debug("Parsing ouput string in DF inspector")
Expand Down
8 changes: 7 additions & 1 deletion inspector/docker_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ type DockerStats struct {
}

// Parse : run custom parsing on output of the command
/*
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
redis1 0.07% 796 KB / 64 MB 1.21% 788 B / 648 B 3.568 MB / 512 KB 2
redis2 0.07% 2.746 MB / 64 MB 4.29% 1.266 KB / 648 B 12.4 MB / 0 B 3
*/
func (i *DockerStats) Parse(output string) {
var values []DockerStatsMetrics
var splitChars string
Expand Down Expand Up @@ -63,7 +68,8 @@ func (i *DockerStats) Parse(output string) {
}
pid, err := strconv.Atoi(columns[13])
if err != nil {
log.Fatal("Could not parse pid for docker stats")
log.Debug("Could not parse pid for docker stats, probably on windows")
pid = 0
}
value := i.createMetric(col, columns[0], columns[1], cpu, memory, pid)
values = append(values, value)
Expand Down
83 changes: 65 additions & 18 deletions inspector/loadavg.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package inspector

import (
"errors"
"fmt"
"strconv"
"strings"

Expand All @@ -16,13 +17,27 @@ type LoadAvgMetrics struct {
Load15M float64
}

// LoadAvg : Parsing the /proc/loadavg output for load average monitoring
type LoadAvg struct {
// LoadAvgLinux : Parsing the /proc/loadavg output for load average monitoring
type LoadAvgLinux struct {
FilePath string
Driver *driver.Driver
Values *LoadAvgMetrics
}

// LoadAvgDarwin : Parsing the `top` output for Load Avg
type LoadAvgDarwin struct {
Command string
Driver *driver.Driver
Values *LoadAvgMetrics
}

// LoadAvgWin : Only grants instantaneous load metrics and not historical
type LoadAvgWin struct {
Command string
Driver *driver.Driver
Values *LoadAvgMetrics
}

func loadavgParseOutput(output string) *LoadAvgMetrics {
var err error
log.Debug("Parsing ouput string in LoadAvg inspector")
Expand All @@ -41,12 +56,6 @@ func loadavgParseOutput(output string) *LoadAvgMetrics {
}
}

type LoadAvgDarwin struct {
Command string
Driver *driver.Driver
Values *LoadAvgMetrics
}

func (i *LoadAvgDarwin) SetDriver(driver *driver.Driver) {
details := (*driver).GetDetails()
if !details.IsDarwin {
Expand All @@ -59,9 +68,12 @@ func (i LoadAvgDarwin) driverExec() driver.Command {
return (*i.Driver).RunCommand
}

// Parse : Parsing for darwin
/*
4.27, 5.04, 4.50
*/
func (i *LoadAvgDarwin) Parse(output string) {
output = strings.TrimSuffix(output, "}")
output = strings.TrimPrefix(output, "{")
output = strings.ReplaceAll(output, ",", "")
i.Values = loadavgParseOutput(output)
}

Expand All @@ -72,48 +84,83 @@ func (i *LoadAvgDarwin) Execute() {
}
}

func (i *LoadAvg) Parse(output string) {
// Parse : Linux Specific Parsing for Load Avg
/*
0.25 0.23 0.14 3/671 9362
*/
func (i *LoadAvgLinux) Parse(output string) {
i.Values = loadavgParseOutput(output)
}

func (i *LoadAvg) SetDriver(driver *driver.Driver) {
func (i *LoadAvgLinux) SetDriver(driver *driver.Driver) {
details := (*driver).GetDetails()
if !details.IsLinux {
panic("Cannot use LoadAvg on drivers outside (linux)")
}
i.Driver = driver
}

func (i LoadAvg) driverExec() driver.Command {
func (i LoadAvgLinux) driverExec() driver.Command {
return (*i.Driver).ReadFile
}

func (i *LoadAvg) Execute() {
func (i *LoadAvgLinux) Execute() {
output, err := i.driverExec()(i.FilePath)
if err == nil {
i.Parse(output)
}
}

//TODO: Windows Equivalents
// of LoadAvg
func (i *LoadAvgWin) Parse(output string) {
output = strings.ReplaceAll(output, "\r", "")
output = strings.ReplaceAll(output, " ", "")
columns := strings.Split(output, "\n")
// Only instantaneous metrics available so append the
// rest as zero
output = columns[1]
output = fmt.Sprintf("%s 0 0", output)
i.Values = loadavgParseOutput(output)
}

func (i *LoadAvgWin) SetDriver(driver *driver.Driver) {
details := (*driver).GetDetails()
if !details.IsWindows {
panic("Cannot use LoadAvgWin on drivers outside (windows)")
}
i.Driver = driver
}

func (i LoadAvgWin) driverExec() driver.Command {
return (*i.Driver).RunCommand
}

func (i *LoadAvgWin) Execute() {
output, err := i.driverExec()(i.Command)
if err == nil {
i.Parse(output)
}
}

// NewLoadAvg : Initialize a new LoadAvg instance
func NewLoadAvg(driver *driver.Driver, _ ...string) (Inspector, error) {
var loadavg Inspector
details := (*driver).GetDetails()
if !(details.IsLinux || details.IsDarwin) {
if !(details.IsLinux || details.IsDarwin || details.IsWindows) {
return nil, errors.New("Cannot use LoadAvg on drivers outside (linux, darwin)")
}
if details.IsLinux {
loadavg = &LoadAvg{
loadavg = &LoadAvgLinux{
FilePath: `/proc/loadavg`,
}
} else if details.IsDarwin {
loadavg = &LoadAvgDarwin{
// Command: `sysctl -n vm.loadavg | awk '{ printf "%.2f %.2f %.2f ", $2, $3, $4 }'`,
Command: `top -l 1 | grep "Load Avg:" | awk '{print $3, $4, $5}'`,
}
} else if details.IsWindows {
loadavg = &LoadAvgWin{
Command: `wmic cpu get loadpercentage`,
}
}
loadavg.SetDriver(driver)
return loadavg, nil
Expand Down
2 changes: 1 addition & 1 deletion inspector/loadavg_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestLoadAvg(t *testing.T) {
testDriver := NewLocalForTest()
loadavg, _ := NewLoadAvg(&testDriver)
loadavg.Execute()
loadavgConcreteLinux, ok := loadavg.(*LoadAvg)
loadavgConcreteLinux, ok := loadavg.(*LoadAvgLinux)
if ok {
if loadavgConcreteLinux.Values == nil {
t.Error("Load metrics for linux did not get set")
Expand Down
Loading

0 comments on commit bacd714

Please sign in to comment.