Skip to content

Commit

Permalink
Improve documentation in readme and cli
Browse files Browse the repository at this point in the history
Switches to the urfave/cli/v2 framework for improved cli paramenter
documentation. This commit also updates the README.md to make the first
usage of this small cli even easier.
  • Loading branch information
lynxplay committed Mar 30, 2021
1 parent ded41e8 commit 8913160
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 53 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:

# Build
- name: Build project
run: 'go build'
run: './scripts/build.sh'

# Release binaries
- name: Release
Expand Down
66 changes: 62 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
carre
========
# carre

------------------------------------------------------------------------------------------------------------------------

Expand All @@ -9,9 +8,68 @@ information but on container basis.

------------------------------------------------------------------------------------------------------------------------

Install
-------
## Install

### Through golang

You may simply install the go project using the following go command:

```shell
go get -u github.com/lynxplay/carre
```

### Release binaries

**Carre** also provides pre-build binaries for finished releases to avoid the requirement for a complete go installation
on every system. The binaries can be found in the respective releases [here](https://github.com/lynxplay/carre/releases)
.

------------------------------------------------------------------------------------------------------------------------

## Usage

### -container (required)

The container parameter specifies the name of the container for which the metrics are to be gathered. It is required as
this is the core point of caree,

### -interval

The interval parameter can specify the duration between each data point collected by caree.

#### Default: 500ms

#### Units: "ns", "us" (or "µs"), "ms", "s", "m", "h"

### -format

The format parameter specifies in which format the output is printed. As of right now the follow formats exist.

- 'CSV' provides a comma separated list of values **<u>including</u>** the csv header defining the collum values.
- 'JSON' provides a set of json data points mapping the respective metric to its value. Each line is an individually
complete json string.

#### Default: JSON

------------------------------------------------------------------------------------------------------------------------

## Examples

```shell
carre --container my_great_container
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
{"%CPU":"0.1","%MEM":"0.2","COMMAND":"java -jar application.jar","PID":"9809","RSS":"130072","START":"22:20","STAT":"Ssl","TIME":"0:04","TTY":"?","USER":"root","VSZ":"19894616"}
```



Expand Down
22 changes: 13 additions & 9 deletions lib/lib.go → cmd/lib.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lib
package cmd

import (
"context"
Expand All @@ -8,6 +8,7 @@ import (
"github.com/docker/docker/client"
"log"
"strings"
"time"
)

var (
Expand All @@ -24,8 +25,8 @@ const (
)

type DisplayContext struct {
Name string
OutputMode OutputMode
Name string
OutputFormat OutputMode
}

func DisplayCurrentStats(dockerClient *client.Client, ctx DisplayContext) {
Expand All @@ -35,11 +36,12 @@ func DisplayCurrentStats(dockerClient *client.Client, ctx DisplayContext) {
return
}

switch ctx.OutputMode {
switch ctx.OutputFormat {
case JSON:
for i := range result.Processes {
process := result.Processes[i]
processValues := make(map[string]string)
processValues["TIMESTAMP"] = time.Now().String()
for j := range process {
processValues[result.Titles[j]] = process[j]
}
Expand All @@ -51,21 +53,23 @@ func DisplayCurrentStats(dockerClient *client.Client, ctx DisplayContext) {
}
case CSV:
if !PrintedCSVHeader {
fmt.Println(strings.Join(result.Titles, ","))
fmt.Println(strings.Join(result.Titles, ",") + ",TIMESTAMP") // Avoid slice reallocation for csv print
PrintedCSVHeader = true
}

for i := range result.Processes {
fmt.Println(strings.Join(result.Processes[i], ","))
fmt.Println(strings.Join(result.Processes[i], ",") + "," + time.Now().String())
}
}
}

func ParseOutputMode(str string) (OutputMode, error) {
func ParseOutputFormat(str string) (OutputMode, error) {
switch strings.ToUpper(str) {
case "CSV":
return CSV, nil
case "JSON":
return JSON, nil
return JSON, nil // Different case than the default case, JSON was parsed correctly!
default:
return CSV, errors.New("failed to parse output mode; defaulting to CSV")
return JSON, errors.New("failed to parse output format; defaulting to JSON")
}
}
38 changes: 38 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cmd

import (
"github.com/docker/docker/client"
"github.com/urfave/cli/v2"
"log"
"os"
"os/signal"
"time"
)

func Execute(ctx *cli.Context) error {
outputFormat, err := ParseOutputFormat(ctx.String("format"))

context := DisplayContext{
Name: ctx.String("container"),
OutputFormat: outputFormat,
}

dockerClient, err := client.NewEnvClient()
if err != nil {
log.Fatalf("Failed to create environment dockerClient: %s", err)
return err
}

signalBus := make(chan os.Signal, 1)
signal.Notify(signalBus, os.Interrupt, os.Kill)

timer := time.NewTicker(ctx.Duration("interval"))
for {
select {
case _ = <-signalBus:
return nil
case _ = <-timer.C:
DisplayCurrentStats(dockerClient, context)
}
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ require (
github.com/docker/docker v1.13.1
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/gonvenience/bunt v1.3.2
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/stretchr/testify v1.7.0 // indirect
github.com/urfave/cli/v2 v2.3.0
golang.org/x/net v0.0.0-20210329181859-df645c7b52b1 // indirect
)
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -30,6 +34,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
Expand Down Expand Up @@ -58,12 +63,20 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
Expand Down Expand Up @@ -102,6 +115,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
Expand All @@ -115,10 +129,13 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
Expand Down
73 changes: 36 additions & 37 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,54 +1,53 @@
package main

import (
"flag"
"github.com/docker/docker/client"
"github.com/gonvenience/bunt"
"github.com/lynxplay/carre/lib"
"github.com/lynxplay/carre/cmd"
"github.com/urfave/cli/v2"
"log"
"os"
"os/signal"
"time"
)

var (
container = flag.String("container", "", "-container <container_name>")
interval = flag.Duration("interval", time.Millisecond*500, "-duration 10s")
output = flag.String("output", "CSV", "-output CSV")
)
var version string

func main() {
flag.Parse()
if "" == *container {
flag.Usage()
_, _ = bunt.Println("Red{-container is required!}")
return
}
mode, err := lib.ParseOutputMode(*output)
if err != nil {
_, _ = bunt.Printf("Orange{WARN: %s}\n", err)
app := &cli.App{
Name: "carre",
Usage: "Docker process data point collection",
Version: getVersion(),
Action: cmd.Execute,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "container",
Aliases: []string{"C"},
Usage: "unique container name",
Required: true,
},
&cli.StringFlag{
Name: "format",
Aliases: []string{"F"},
Value: "JSON",
Usage: "output format of caree",
},
&cli.DurationFlag{
Name: "interval",
Aliases: []string{"I"},
Value: 500 * time.Millisecond,
Usage: "interval between data point collection",
},
},
}
app.EnableBashCompletion = true

context := lib.DisplayContext{
Name: *container,
OutputMode: mode,
}

dockerClient, err := client.NewEnvClient()
err := app.Run(os.Args)
if err != nil {
log.Fatalf("Failed to create environment dockerClient: %s", err)
log.Fatal(err)
}
}

signalBus := make(chan os.Signal, 1)
signal.Notify(signalBus, os.Interrupt, os.Kill)

timer := time.NewTicker(*interval)
for {
select {
case _ = <-signalBus:
return
case _ = <-timer.C:
lib.DisplayCurrentStats(dockerClient, context)
}
func getVersion() string {
if version == "" {
return "develop"
}
return version
}
2 changes: 1 addition & 1 deletion scripts/build.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ while read -r OS ARCH; do
echo -e "Running go build of version \\033[1;3m${TOOL_VERSION}\\033[0m for \\033[1;91m${OS}\\033[0m/\\033[1;31m${ARCH}\\033[0m: \\033[93m$(basename "${TARGET_FILE}")\\033[0m"
CGO_ENABLED=0 GOOS="${OS}" GOARCH="${ARCH}" go build \
-tags netgo \
-ldflags "-s -w -extldflags '-static'" \
-ldflags "-s -w -extldflags '-static' -X main.version=${TOOL_VERSION}" \
-o "${TARGET_FILE}" \
main.go &

Expand Down

0 comments on commit 8913160

Please sign in to comment.