Skip to content

Commit

Permalink
Add support for exporting exitcode of script as metric
Browse files Browse the repository at this point in the history
  • Loading branch information
Doherty, Rory committed Jul 20, 2020
1 parent 75665b8 commit 01b9809
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 15 deletions.
30 changes: 18 additions & 12 deletions script_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os"
"os/exec"
"regexp"
"syscall"
"time"

"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -40,32 +41,35 @@ type Script struct {
type Measurement struct {
Script *Script
Success int
ExitCode int
Duration float64
}

func runScript(script *Script) error {
func runScript(script *Script) (err error, rc int) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(script.Timeout)*time.Second)
defer cancel()

bashCmd := exec.CommandContext(ctx, *shell)
cmd := exec.CommandContext(ctx, *shell)

bashIn, err := bashCmd.StdinPipe()
stdin, err := cmd.StdinPipe()

if err != nil {
return err
return err, 1
}

if err = bashCmd.Start(); err != nil {
return err
if _, err = stdin.Write([]byte(script.Content)); err != nil {
return err, 1
}
stdin.Close()

if _, err = bashIn.Write([]byte(script.Content)); err != nil {
return err
if err = cmd.Run(); err != nil {
exitError := err.(*exec.ExitError)
rc = exitError.Sys().(syscall.WaitStatus).ExitStatus()
} else {
rc = cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
}

bashIn.Close()

return bashCmd.Wait()
return err, rc
}

func runScripts(scripts []*Script) []*Measurement {
Expand All @@ -77,7 +81,7 @@ func runScripts(scripts []*Script) []*Measurement {
go func(script *Script) {
start := time.Now()
success := 0
err := runScript(script)
err, rc := runScript(script)
duration := time.Since(start).Seconds()

if err == nil {
Expand All @@ -91,6 +95,7 @@ func runScripts(scripts []*Script) []*Measurement {
Script: script,
Duration: duration,
Success: success,
ExitCode: rc,
}
}(script)
}
Expand Down Expand Up @@ -144,6 +149,7 @@ func scriptRunHandler(w http.ResponseWriter, r *http.Request, config *Config) {
for _, measurement := range measurements {
fmt.Fprintf(w, "script_duration_seconds{script=\"%s\"} %f\n", measurement.Script.Name, measurement.Duration)
fmt.Fprintf(w, "script_success{script=\"%s\"} %d\n", measurement.Script.Name, measurement.Success)
fmt.Fprintf(w, "script_exit_code{script=\"%s\"} %d\n", measurement.Script.Name, measurement.ExitCode)
}
}

Expand Down
11 changes: 8 additions & 3 deletions script_exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ func TestRunScripts(t *testing.T) {
expectedResults := map[string]struct {
success int
minDuration float64
exitCode int
}{
"success": {1, 0},
"failure": {0, 0},
"timeout": {0, 2},
"success": {1, 0, 0},
"failure": {0, 0, 1},
"timeout": {0, 2, -1},
}

for _, measurement := range measurements {
Expand All @@ -34,6 +35,10 @@ func TestRunScripts(t *testing.T) {
if measurement.Duration < expectedResult.minDuration {
t.Errorf("Expected duration %f < %f: %s", measurement.Duration, expectedResult.minDuration, measurement.Script.Name)
}

if measurement.ExitCode != expectedResult.exitCode {
t.Errorf("Expected exit code %d != %d: %s", measurement.ExitCode, expectedResult.exitCode, measurement.Script.Name)
}
}
}

Expand Down

0 comments on commit 01b9809

Please sign in to comment.