Skip to content

Commit

Permalink
functional docker-stats inspector parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
deven96 committed Oct 26, 2021
1 parent 270a1ee commit 2f77db9
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 3 deletions.
96 changes: 96 additions & 0 deletions inspector/docker_stats.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package inspector

import (
log "github.com/sirupsen/logrus"
"strconv"
"strings"
)

// DockerStatsMetrics : Metrics used by DockerStats
type DockerStatsMetrics struct {
ContainerID string
ContainerName string
CPU float64
MemUsage float64
Limit float64
MemPercent float64
Pid int
}

// DockerStats : Parsing the `docker stats` output for container monitoring
type DockerStats struct {
fields
// We want do display disk values in GB
DisplayByteSize string
// Values of metrics being read
Values []DockerStatsMetrics
}

// Parse : run custom parsing on output of the command
func (i *DockerStats) Parse(output string) {
var values []DockerStatsMetrics
log.Debug("Parsing ouput string in DockerStats inspector")
lines := strings.Split(output, "\n")
for index, line := range lines {
// skip title line
if index == 0 {
continue
}
columns := strings.Fields(line)
if len(columns) == 14 {
cpu, err := strconv.ParseFloat(strings.TrimSuffix(columns[2], "%"), 64)
if err != nil {
log.Fatal("Could not parse cpu for docker stats")
}
memory, err := strconv.ParseFloat(strings.TrimSuffix(columns[6], "%"), 64)
if err != nil {
log.Fatal("Could not parse cpu for docker stats")
}
col := []string{
columns[3],
columns[5],
}
pid, err := strconv.Atoi(columns[13])
if err != nil {
log.Fatal("Could not parse pid for docker stats")
}
value := i.createMetric(col, columns[0], columns[1], cpu, memory, pid)
values = append(values, value)
}
}
i.Values = values
}

func (i DockerStats) createMetric(
columns []string,
containerID string,
containerName string,
cpu float64,
memory float64,
pid int) DockerStatsMetrics {
lastMem := len(columns[0]) - 3
lastLim := len(columns[1]) - 3
memusageSize := columns[0][lastMem:]
limitSize := columns[1][lastLim:]
return DockerStatsMetrics{
ContainerID: containerID,
ContainerName: containerName,
CPU: cpu,
MemUsage: NewByteSize(columns[0][:lastMem], memusageSize).format(i.DisplayByteSize),
Limit: NewByteSize(columns[1][:lastLim], limitSize).format(i.DisplayByteSize),
MemPercent: memory,
Pid: pid,
}
}

// NewDockerStats : Initialize a new DockerStats instance
func NewDockerStats() *DockerStats {
return &DockerStats{
fields: fields{
Type: Command,
Command: `docker stats --no-stream`,
},
DisplayByteSize: `GB`,
}

}
5 changes: 3 additions & 2 deletions inspector/inspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ const (
)

var inspectorMap = map[string]Inspector{
`disk`: NewDF(),
`meminfo`: NewMemInfo(),
`disk`: NewDF(),
`meminfo`: NewMemInfo(),
`dockerstats`: NewDockerStats(),
}

type fields struct {
Expand Down
5 changes: 4 additions & 1 deletion inspector/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package inspector

import (
"fmt"
log "github.com/sirupsen/logrus"
"math"
"strconv"
Expand Down Expand Up @@ -34,7 +35,9 @@ func NewByteSize(byteCount string, unit string) *ByteSize {

func index(arr []string, str string) float64 {
for index, a := range arr {
if a == str {
// Match GB to GB and GiB
if a == str || fmt.Sprintf(
`%si%s`, string(a[:len(a)-1]), string(a[len(a)-1])) == str {
return float64(index)
}
}
Expand Down
15 changes: 15 additions & 0 deletions integration/integration_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,18 @@ func TestMemInfoonLocal(t *testing.T) {
}
fmt.Printf(`%#v`, i.Values)
}

func TestDockerStatsonLocal(t *testing.T) {
d := driver.Local{}
// can either use NewDF() or get the interface and perform type assertion
i := (inspector.GetInspector(`dockerstats`)).(*inspector.DockerStats)
output, err := d.RunCommand(i.String())
if err != nil {
t.Error(err)
}
i.Parse(output)
if len(i.Values) == 0 {
t.Error("showing no running container")
}
fmt.Printf(`%#v`, i.Values)
}

0 comments on commit 2f77db9

Please sign in to comment.