Skip to content

Commit

Permalink
Merge pull request #36 from ricoberger/add-exit-code-metric
Browse files Browse the repository at this point in the history
Add metric for the exit code of a script
  • Loading branch information
ricoberger authored Sep 15, 2021
2 parents 5ea1547 + 9d1bb84 commit 5eb48ef
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 13 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The script_exporter is a [Prometheus](https://prometheus.io) exporter to execute

To run the script_exporter you can use the one of the binaries from the [release](https://github.com/ricoberger/script_exporter/releases) page or the [Docker image](https://hub.docker.com/r/ricoberger/script_exporter). You can also build the script_exporter by yourself by running the following commands:

```
```sh
git clone https://github.com/ricoberger/script_exporter.git
cd script_exporter
make build
Expand All @@ -33,18 +33,18 @@ You can also deploy the script_exporter to Kubernetes. An example Deployment fil

The script_exporter is configured via a configuration file and command-line flags.

```
```txt
Usage of ./bin/script_exporter:
-config.file file
Configuration file in YAML format. (default "config.yaml")
Configuration file in YAML format. (default "config.yaml")
-create-token
Create bearer token for authentication.
Create bearer token for authentication.
-timeout-offset seconds
Offset to subtract from Prometheus-supplied timeout in seconds. (default 0.5)
-version
Show version information.
Show version information.
-web.listen-address string
Address to listen on for web interface and telemetry. (default ":9469")
Address to listen on for web interface and telemetry. (default ":9469")
```

The configuration file is written in YAML format, defined by the scheme described below.
Expand Down
2 changes: 2 additions & 0 deletions pkg/exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const (
scriptSuccessType = "# TYPE script_success gauge"
scriptDurationSecondsHelp = "# HELP script_duration_seconds Script execution time, in seconds."
scriptDurationSecondsType = "# TYPE script_duration_seconds gauge"
scriptExitCodeHelp = "# HELP script_exit_code The exit code of the script."
scriptExitCodeType = "# TYPE script_exit_code gauge"
)

type Exporter struct {
Expand Down
8 changes: 4 additions & 4 deletions pkg/exporter/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ func (e *Exporter) MetricsHandler(w http.ResponseWriter, r *http.Request) {
// configuration file.
timeout := getTimeout(r, e.timeoutOffset, e.Config.GetMaxTimeout(scriptName))

output, err := runScript(timeout, e.Config.GetTimeoutEnforced(scriptName), append(strings.Split(script, " "), paramValues...))
output, exitCode, err := runScript(timeout, e.Config.GetTimeoutEnforced(scriptName), append(strings.Split(script, " "), paramValues...))
if err != nil {
log.Printf("Script failed: %s\n", err.Error())
fmt.Fprintf(w, "%s\n%s\n%s_success{script=\"%s\"} %d\n%s\n%s\n%s_duration_seconds{script=\"%s\"} %f\n", scriptSuccessHelp, scriptSuccessType, namespace, scriptName, 0, scriptDurationSecondsHelp, scriptDurationSecondsType, namespace, scriptName, time.Since(scriptStartTime).Seconds())
fmt.Fprintf(w, "%s\n%s\n%s_success{script=\"%s\"} %d\n%s\n%s\n%s_duration_seconds{script=\"%s\"} %f\n%s\n%s\n%s_exit_code{script=\"%s\"} %d\n", scriptSuccessHelp, scriptSuccessType, namespace, scriptName, 0, scriptDurationSecondsHelp, scriptDurationSecondsType, namespace, scriptName, time.Since(scriptStartTime).Seconds(), scriptExitCodeHelp, scriptExitCodeType, namespace, scriptName, exitCode)
return
}

// Get ignore output parameter and only return success and duration seconds if 'true'
outputParam := params.Get("output")
if outputParam == "ignore" {
fmt.Fprintf(w, "%s\n%s\n%s_success{script=\"%s\"} %d\n%s\n%s\n%s_duration_seconds{script=\"%s\"} %f\n", scriptSuccessHelp, scriptSuccessType, namespace, scriptName, 1, scriptDurationSecondsHelp, scriptDurationSecondsType, namespace, scriptName, time.Since(scriptStartTime).Seconds())
fmt.Fprintf(w, "%s\n%s\n%s_success{script=\"%s\"} %d\n%s\n%s\n%s_duration_seconds{script=\"%s\"} %f\n%s\n%s\n%s_exit_code{script=\"%s\"} %d\n", scriptSuccessHelp, scriptSuccessType, namespace, scriptName, 1, scriptDurationSecondsHelp, scriptDurationSecondsType, namespace, scriptName, time.Since(scriptStartTime).Seconds(), scriptExitCodeHelp, scriptExitCodeType, namespace, scriptName, exitCode)
return
}

Expand Down Expand Up @@ -103,7 +103,7 @@ func (e *Exporter) MetricsHandler(w http.ResponseWriter, r *http.Request) {
}
}

fmt.Fprintf(w, "%s\n%s\n%s_success{script=\"%s\"} %d\n%s\n%s\n%s_duration_seconds{script=\"%s\"} %f\n%s\n", scriptSuccessHelp, scriptSuccessType, namespace, scriptName, 1, scriptDurationSecondsHelp, scriptDurationSecondsType, namespace, scriptName, time.Since(scriptStartTime).Seconds(), formatedOutput)
fmt.Fprintf(w, "%s\n%s\n%s_success{script=\"%s\"} %d\n%s\n%s\n%s_duration_seconds{script=\"%s\"} %f\n%s\n%s\n%s_exit_code{script=\"%s\"} %d\n%s\n", scriptSuccessHelp, scriptSuccessType, namespace, scriptName, 1, scriptDurationSecondsHelp, scriptDurationSecondsType, namespace, scriptName, time.Since(scriptStartTime).Seconds(), scriptExitCodeHelp, scriptExitCodeType, namespace, scriptName, exitCode, formatedOutput)
}

// SetupMetrics creates and registers our internal Prometheus metrics,
Expand Down
10 changes: 7 additions & 3 deletions pkg/exporter/scripts.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
// be subject to abrupt termination regardless of any 'enforced:'
// settings. Right now, abrupt termination requires opting in in
// the configuration file.
func runScript(timeout float64, enforced bool, args []string) (string, error) {
func runScript(timeout float64, enforced bool, args []string) (string, int, error) {
var output []byte
var err error

Expand Down Expand Up @@ -73,10 +73,14 @@ func runScript(timeout float64, enforced bool, args []string) (string, error) {

output, err = cmd.Output()
if err != nil {
return "", err
if exitError, ok := err.(*exec.ExitError); ok {
return "", exitError.ExitCode(), err
}

return "", -1, err
}

return string(output), nil
return string(output), 0, nil
}

// getTimeout gets the Prometheus scrape timeout (in seconds) from the
Expand Down

0 comments on commit 5eb48ef

Please sign in to comment.