go-check is a Golang library to help with development of monitoring plugins for tools like Icinga.
See the documentation on pkg.go.dev for more details and examples.
With the NewConfig constructor you can quickly create a CLI monitoring plugin:
package main
import (
"fmt"
"github.com/NETWAYS/go-check"
)
func main() {
// Global configuration of the plugin
config := check.NewConfig()
config.Name = "check_test"
config.Readme = `Test Plugin`
config.Version = "1.0.0"
// Command line arguments
_ = config.FlagSet.StringP("hostname", "H", "localhost", "Hostname to check")
config.ParseArguments()
// Handle exit with the desired exit code
check.Exit(check.OK, fmt.Sprintf("Everything is fine - answer=%d", 42))
// Output:
// [OK] - Everything is fine - answer=42
}However, the go-check library does not require you to use the Config type.
The library provides predefined return or exit codes:
check.OK
check.Warning
check.Critical
check.Unknown
// These exit codes implement the Stringer interface
fmt.Println(check.OK)To convert an integer or string into an exit code
unknown, err := NewStatus(3)
warning, err := NewStatusFromString("Warning")
See also: https://www.monitoring-plugins.org/doc/guidelines.html#AEN74
The Exit function can be used to cause an exit with the given status code.
check.Exit(check.OK, fmt.Sprintf("Everything is fine - value=%d", 42)) // OK, 0
// With critical
check.Exit(check.Critical, "Everything is broken", "Do something!") // CRITICAL, 2The ExitWithPerfdata function can be used to include performance data in the output.
perfdata := check.PerfdataList{}
perfdata.Add(&check.Perfdata{Label: "packages_lost", Value: 42})
check.ExitWithPerfdata(check.OK, perfdata, "Everything is fine", "Package loss nominal")The ExitError function can be used to cause an exit with the given error.
err := fmt.Errorf("connection to %s has been timed out", "localhost:12345")
check.ExitError(err)
// UNKNOWN, 3You can use defer check.CatchPanic() to ensure a check plugin will always exit with a proper code,
even if the code panics.
HandleTimeout is a helper for a goroutine, to wait for signals and timeout, and exit with a proper code.
checkPluginTimeoutInSeconds := 10
go check.HandleTimeout(checkPluginTimeoutInSeconds)Threshold objects represent monitoring plugin thresholds that have methods to evaluate if a given input is within the range.
They can be created with the ParseThreshold parser.
warnThreshold, err := check.ParseThreshold("~:3")
if err != nil {
// Handle the error
}
if warnThreshold.DoesViolate(3.6) {
fmt.Println("Not great, not terrible.")
}See also: https://www.monitoring-plugins.org/doc/guidelines.html#THRESHOLDFORMAT
The Perfdata object represents monitoring plugin performance data that relates to the actual execution of a host or service check.
var pl check.PerfdataList
pl.Add(&check.Perfdata{
Label: "process.cpu.percent",
Value: 25,
Uom: "%",
Warn: &check.Threshold{Lower: check.NegInf, Upper: 50},
Crit: &check.Threshold{Lower: check.NegInf, Upper: 90},
Min: 0,
Max: 100})
fmt.Println(pl.String())See also: https://www.monitoring-plugins.org/doc/guidelines.html#AEN197
The WorstState helper can be used to determine the worst exit status from a set of exit states.
allStates = []check.Status{check.OK, check.Critical, check.Warning, check.Unknown}
rc := result.WorstState(allStates...)The Overall and PartialResult objects can be used to represent a simple parent-child relationship.
An Overall can contain multiple subchecks. The final exit of the Overall will be automatically determined by the worst state of a PartialResult.
o := Overall{}
o.Add(0, "Something is OK")
pr := NewPartialResult()
pr.SetOutput("Something happened")
pr.SetState(check.OK)
o.AddSubcheck(pr)
fmt.Println(o.GetOutput())
// states: ok=1
// [OK] Something is OK
// \_ [OK] Something happenedOverall is concurrency-safe.
ParseBytes is a helper that can be used to parse string containing IEC or SI bytes into the number of bytes.
b, err := ParseBytes("2MiB")
// uint64 2 * 1024 * 1024
b, err := ParseBytes("1MB")
// uint64 1000 * 1000BytesIEC and BytesSI can be used to format a byte value with human-readable string output.
b := convert.BytesIEC(999)
fmt.Println(b)
// "999B"
b := convert.BytesIEC(999 * 1024)
fmt.Println(b)
// "999KiB"
b := convert.BytesIEC(999 * 1024 * 1024 * 1024 * 1024)
fmt.Println(b)
// "999TiB"
b := convert.BytesSI(999)
fmt.Println(b)
// "999B"
b := convert.BytesSI(999 * 1000)
fmt.Println(b)
// "999KB"
b := convert.BytesSI(999 * 1000 * 1000 * 1000 * 1000)
fmt.Println(b)
// "999TB"A few plugins using go-check:
Copyright (c) 2020 NETWAYS GmbH
This library is distributed under the GPL-2.0 or newer license found in the COPYING file.