From fd3de634f2e4e0aa71b4cdf39b0802947698b881 Mon Sep 17 00:00:00 2001 From: Michael Insel Date: Thu, 7 Feb 2019 17:27:15 +0100 Subject: [PATCH] Implement performance data output This implements performance data output --- cmd/check_fritz/check_connection.go | 13 ++- cmd/check_fritz/check_device.go | 12 ++- cmd/check_fritz/check_downstream.go | 36 ++++++-- cmd/check_fritz/check_smart.go | 36 +++++++- cmd/check_fritz/check_upstream.go | 34 +++++-- pkg/perfdata/perfdata.go | 52 +++++++++++ pkg/perfdata/perfdata_test.go | 138 ++++++++++++++++++++++++++++ pkg/thresholds/thresholds.go | 9 ++ 8 files changed, 313 insertions(+), 17 deletions(-) create mode 100644 pkg/perfdata/perfdata.go create mode 100644 pkg/perfdata/perfdata_test.go diff --git a/cmd/check_fritz/check_connection.go b/cmd/check_fritz/check_connection.go index f19febf..7d5822b 100644 --- a/cmd/check_fritz/check_connection.go +++ b/cmd/check_fritz/check_connection.go @@ -2,6 +2,9 @@ package main import ( "fmt" + "strconv" + + "github.com/mcktr/check_fritz/pkg/perfdata" "github.com/mcktr/check_fritz/pkg/fritz" ) @@ -53,7 +56,15 @@ func CheckConnectionUptime(aI ArgumentInformation) { return } - fmt.Print("OK - Connection Uptime: " + resp.NewUptime + "\n") + uptime, err := strconv.ParseFloat(resp.NewUptime, 64) + + if HandleError(err) { + return + } + + perfData := perfdata.CreatePerformanceData("uptime", uptime, "s") + + fmt.Print("OK - Connection Uptime: " + fmt.Sprintf("%.f", uptime) + " " + perfData.GetPerformanceDataAsString() + "\n") GlobalReturnCode = exitOk } diff --git a/cmd/check_fritz/check_device.go b/cmd/check_fritz/check_device.go index eaf9028..d5ad8dd 100644 --- a/cmd/check_fritz/check_device.go +++ b/cmd/check_fritz/check_device.go @@ -2,8 +2,10 @@ package main import ( "fmt" + "strconv" "github.com/mcktr/check_fritz/pkg/fritz" + "github.com/mcktr/check_fritz/pkg/perfdata" ) // CheckDeviceUptime checks the uptime of the device @@ -24,7 +26,15 @@ func CheckDeviceUptime(aI ArgumentInformation) { return } - fmt.Print("OK - Device Uptime: " + resp.NewUpTime + "\n") + uptime, err := strconv.ParseFloat(resp.NewUpTime, 64) + + if HandleError(err) { + return + } + + perfData := perfdata.CreatePerformanceData("uptime", uptime, "s") + + fmt.Print("OK - Device Uptime: " + fmt.Sprintf("%.0f", uptime) + " " + perfData.GetPerformanceDataAsString() + "\n") GlobalReturnCode = exitOk } diff --git a/cmd/check_fritz/check_downstream.go b/cmd/check_fritz/check_downstream.go index 6c54b06..4408e5b 100644 --- a/cmd/check_fritz/check_downstream.go +++ b/cmd/check_fritz/check_downstream.go @@ -5,6 +5,8 @@ import ( "strconv" "strings" + "github.com/mcktr/check_fritz/pkg/perfdata" + "github.com/mcktr/check_fritz/pkg/fritz" "github.com/mcktr/check_fritz/pkg/thresholds" ) @@ -29,6 +31,7 @@ func CheckDownstreamMax(aI ArgumentInformation) { } downstream, err := strconv.ParseFloat(resp.NewMaxDS, 64) + perfData := perfdata.CreatePerformanceData("downstream_max", downstream, "") if HandleError(err) { return @@ -38,6 +41,14 @@ func CheckDownstreamMax(aI ArgumentInformation) { GlobalReturnCode = exitOk + if thresholds.GetThresholdsStatus(aI.Warning) { + perfData.SetWarning(aI.Warning) + } + + if thresholds.GetThresholdsStatus(aI.Critical) { + perfData.SetCritical(aI.Critical) + } + if thresholds.CheckLower(aI.Warning, downstream) { GlobalReturnCode = exitWarning } @@ -46,13 +57,15 @@ func CheckDownstreamMax(aI ArgumentInformation) { GlobalReturnCode = exitCritical } + output := " - Max Downstream: " + fmt.Sprintf("%.2f", downstream) + " Mbit/s " + perfData.GetPerformanceDataAsString() + switch GlobalReturnCode { case exitOk: - fmt.Print("OK - Max Downstream: " + fmt.Sprintf("%.2f", downstream) + " Mbit/s \n") + fmt.Print("OK" + output + "\n") case exitWarning: - fmt.Print("WARNING - Max Downstream " + fmt.Sprintf("%.2f", downstream) + " Mbit/s\n") + fmt.Print("WARNING" + output + "\n") case exitCritical: - fmt.Print("CRITICAL - Max Downstream: " + fmt.Sprintf("%.2f", downstream) + " Mbit/s \n") + fmt.Print("CRITICAL" + output + "\n") default: GlobalReturnCode = exitUnknown fmt.Print("UNKNWON - Not able to calculate maximum downstream\n") @@ -87,9 +100,18 @@ func CheckDownstreamCurrent(aI ArgumentInformation) { } downstream = downstream * 8 / 1000000 + perfData := perfdata.CreatePerformanceData("downstream_current", downstream, "") GlobalReturnCode = exitOk + if thresholds.GetThresholdsStatus(aI.Warning) { + perfData.SetWarning(aI.Warning) + } + + if thresholds.GetThresholdsStatus(aI.Critical) { + perfData.SetCritical(aI.Critical) + } + if thresholds.CheckUpper(aI.Warning, downstream) { GlobalReturnCode = exitWarning } @@ -98,13 +120,15 @@ func CheckDownstreamCurrent(aI ArgumentInformation) { GlobalReturnCode = exitCritical } + output := " - Current Downstream: " + fmt.Sprintf("%.2f", downstream) + " Mbit/s \n " + perfData.GetPerformanceDataAsString() + switch GlobalReturnCode { case exitOk: - fmt.Print("OK - Current Downstream: " + fmt.Sprintf("%.2f", downstream) + " Mbit/s \n") + fmt.Print("OK" + output + "\n") case exitWarning: - fmt.Print("WARNING - Current Downstream " + fmt.Sprintf("%.2f", downstream) + " Mbit/s\n") + fmt.Print("WARNING" + output + "\n") case exitCritical: - fmt.Print("CRITICAL - Current Downstream: " + fmt.Sprintf("%.2f", downstream) + " Mbit/s \n") + fmt.Print("CRITICAL" + output + "\n") default: GlobalReturnCode = exitUnknown fmt.Print("UNKNWON - Not able to calculate current downstream\n") diff --git a/cmd/check_fritz/check_smart.go b/cmd/check_fritz/check_smart.go index c0a946c..7469965 100644 --- a/cmd/check_fritz/check_smart.go +++ b/cmd/check_fritz/check_smart.go @@ -4,6 +4,8 @@ import ( "fmt" "strconv" + "github.com/mcktr/check_fritz/pkg/perfdata" + "github.com/mcktr/check_fritz/pkg/fritz" "github.com/mcktr/check_fritz/pkg/thresholds" ) @@ -40,9 +42,18 @@ func CheckSmartThermometer(aI ArgumentInformation) { } currentTemp = currentTemp / 10.0 + perfData := perfdata.CreatePerformanceData("temperature", currentTemp, "") GlobalReturnCode = exitOk + if thresholds.GetThresholdsStatus(aI.Warning) { + perfData.SetWarning(aI.Warning) + } + + if thresholds.GetThresholdsStatus(aI.Critical) { + perfData.SetCritical(aI.Critical) + } + if thresholds.CheckLower(aI.Warning, currentTemp) { GlobalReturnCode = exitWarning } @@ -50,7 +61,8 @@ func CheckSmartThermometer(aI ArgumentInformation) { if thresholds.CheckLower(aI.Critical, currentTemp) { GlobalReturnCode = exitCritical } - output := "- " + resp.NewProductName + " " + resp.NewFirmwareVersion + " - " + resp.NewDeviceName + " " + resp.NewPresent + " " + fmt.Sprintf("%.2f", currentTemp) + " °C" + + output := "- " + resp.NewProductName + " " + resp.NewFirmwareVersion + " - " + resp.NewDeviceName + " " + resp.NewPresent + " " + fmt.Sprintf("%.2f", currentTemp) + " °C " + perfData.GetPerformanceDataAsString() switch GlobalReturnCode { case exitOk: @@ -85,6 +97,7 @@ func CheckSmartSocketPower(aI ArgumentInformation) { } currentPower, err := strconv.ParseFloat(resp.NewMultimeterPower, 64) + perfData := perfdata.CreatePerformanceData("power", currentPower, "") if HandleError(err) { return @@ -94,6 +107,14 @@ func CheckSmartSocketPower(aI ArgumentInformation) { GlobalReturnCode = exitOk + if thresholds.GetThresholdsStatus(aI.Warning) { + perfData.SetWarning(aI.Warning) + } + + if thresholds.GetThresholdsStatus(aI.Critical) { + perfData.SetCritical(aI.Critical) + } + if thresholds.CheckUpper(aI.Warning, currentPower) { GlobalReturnCode = exitWarning } @@ -102,7 +123,7 @@ func CheckSmartSocketPower(aI ArgumentInformation) { GlobalReturnCode = exitCritical } - output := "- " + resp.NewProductName + " " + resp.NewFirmwareVersion + " - " + resp.NewDeviceName + " " + resp.NewPresent + " " + fmt.Sprintf("%.2f", currentPower) + " W" + output := "- " + resp.NewProductName + " " + resp.NewFirmwareVersion + " - " + resp.NewDeviceName + " " + resp.NewPresent + " " + fmt.Sprintf("%.2f", currentPower) + " W " + perfData.GetPerformanceDataAsString() switch GlobalReturnCode { case exitOk: @@ -143,9 +164,18 @@ func CheckSmartSocketEnergy(aI ArgumentInformation) { } currentEnergy = currentEnergy / 1000.0 + perfData := perfdata.CreatePerformanceData("energy", currentEnergy, "") GlobalReturnCode = exitOk + if thresholds.GetThresholdsStatus(aI.Warning) { + perfData.SetWarning(aI.Warning) + } + + if thresholds.GetThresholdsStatus(aI.Critical) { + perfData.SetCritical(aI.Critical) + } + if thresholds.CheckUpper(aI.Warning, currentEnergy) { GlobalReturnCode = exitWarning } @@ -154,7 +184,7 @@ func CheckSmartSocketEnergy(aI ArgumentInformation) { GlobalReturnCode = exitCritical } - output := "- " + resp.NewProductName + " " + resp.NewFirmwareVersion + " - " + resp.NewDeviceName + " " + resp.NewPresent + " " + fmt.Sprintf("%.2f", currentEnergy) + " kWh" + output := "- " + resp.NewProductName + " " + resp.NewFirmwareVersion + " - " + resp.NewDeviceName + " " + resp.NewPresent + " " + fmt.Sprintf("%.2f", currentEnergy) + " kWh " + perfData.GetPerformanceDataAsString() switch GlobalReturnCode { case exitOk: diff --git a/cmd/check_fritz/check_upstream.go b/cmd/check_fritz/check_upstream.go index bdddc90..61b58d3 100644 --- a/cmd/check_fritz/check_upstream.go +++ b/cmd/check_fritz/check_upstream.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/mcktr/check_fritz/pkg/fritz" + "github.com/mcktr/check_fritz/pkg/perfdata" "github.com/mcktr/check_fritz/pkg/thresholds" ) @@ -35,9 +36,17 @@ func CheckUpstreamMax(aI ArgumentInformation) { } upstream = upstream * 8 / 1000000 + perfData := perfdata.CreatePerformanceData("upstream_max", upstream, "") GlobalReturnCode = exitOk + if thresholds.GetThresholdsStatus(aI.Warning) { + perfData.SetWarning(aI.Warning) + } + + if thresholds.GetThresholdsStatus(aI.Critical) { + perfData.SetCritical(aI.Critical) + } if thresholds.CheckLower(aI.Warning, upstream) { GlobalReturnCode = exitWarning } @@ -46,13 +55,15 @@ func CheckUpstreamMax(aI ArgumentInformation) { GlobalReturnCode = exitCritical } + output := " - Max Upstream: " + fmt.Sprintf("%.2f", upstream) + " Mbit/s " + perfData.GetPerformanceDataAsString() + switch GlobalReturnCode { case exitOk: - fmt.Print("OK - Max Upstream: " + fmt.Sprintf("%.2f", upstream) + " Mbit/s \n") + fmt.Print("OK" + output + "\n") case exitWarning: - fmt.Print("WARNING - Max Upstream " + fmt.Sprintf("%.2f", upstream) + " Mbit/s\n") + fmt.Print("WARNING" + output + "\n") case exitCritical: - fmt.Print("CRITICAL - Max Upstream: " + fmt.Sprintf("%.2f", upstream) + " Mbit/s \n") + fmt.Print("CRITICAL" + output + "\n") default: GlobalReturnCode = exitUnknown fmt.Print("UNKNWON - Not able to calculate maximum upstream\n") @@ -87,9 +98,18 @@ func CheckUpstreamCurrent(aI ArgumentInformation) { } upstream = upstream * 8 / 1000000 + perfData := perfdata.CreatePerformanceData("upstream_current", upstream, "") GlobalReturnCode = exitOk + if thresholds.GetThresholdsStatus(aI.Warning) { + perfData.SetWarning(aI.Warning) + } + + if thresholds.GetThresholdsStatus(aI.Critical) { + perfData.SetCritical(aI.Critical) + } + if thresholds.CheckUpper(aI.Warning, upstream) { GlobalReturnCode = exitWarning } @@ -98,13 +118,15 @@ func CheckUpstreamCurrent(aI ArgumentInformation) { GlobalReturnCode = exitCritical } + output := " - Current Upstream: " + fmt.Sprintf("%.2f", upstream) + " Mbit/s \n " + perfData.GetPerformanceDataAsString() + switch GlobalReturnCode { case exitOk: - fmt.Print("OK - Current Upstream: " + fmt.Sprintf("%.2f", upstream) + " Mbit/s \n") + fmt.Print("OK" + output + "\n") case exitWarning: - fmt.Print("WARNING - Current Upstream " + fmt.Sprintf("%.2f", upstream) + " Mbit/s\n") + fmt.Print("WARNING" + output + "\n") case exitCritical: - fmt.Print("CRITICAL - Current Upstream: " + fmt.Sprintf("%.2f", upstream) + " Mbit/s \n") + fmt.Print("CRITICAL" + output + "\n") default: GlobalReturnCode = exitUnknown fmt.Print("UNKNWON - Not able to calculate current upstream\n") diff --git a/pkg/perfdata/perfdata.go b/pkg/perfdata/perfdata.go new file mode 100644 index 0000000..0df5d65 --- /dev/null +++ b/pkg/perfdata/perfdata.go @@ -0,0 +1,52 @@ +package perfdata + +import "fmt" + +// PerformanceData is the data structure for check performance data +type PerformanceData struct { + Label string + Value float64 + UOM string + Warning string + Critical string + Minimum string + Maximum string +} + +// CreatePerformanceData creates and returns a new PerformanceData object +func CreatePerformanceData(Label string, Value float64, UOM string) *PerformanceData { + var pd PerformanceData + + pd.Label = Label + pd.Value = Value + pd.UOM = UOM + + return &pd +} + +// SetWarning sets the warning value of a PerformanceData object +func (pd *PerformanceData) SetWarning(Warning float64) { + pd.Warning = fmt.Sprintf("%f", Warning) + +} + +// SetCritical sets the critical value of a PerformanceData object +func (pd *PerformanceData) SetCritical(Critical float64) { + pd.Critical = fmt.Sprintf("%f", Critical) + +} + +// SetMinimum sets the minimum value of a PerformanceData object +func (pd *PerformanceData) SetMinimum(Minimum float64) { + pd.Minimum = fmt.Sprintf("%f", Minimum) +} + +// SetMaximum sets the maximum value of a PerformanceData object +func (pd *PerformanceData) SetMaximum(Maximum float64) { + pd.Maximum = fmt.Sprintf("%f", Maximum) +} + +// GetPerformanceDataAsString returns a PerformanceData object as formatted string +func (pd *PerformanceData) GetPerformanceDataAsString() string { + return fmt.Sprintf("| '%s'=%f%s;%s;%s;%s;%s", pd.Label, pd.Value, pd.UOM, pd.Warning, pd.Critical, pd.Minimum, pd.Maximum) +} diff --git a/pkg/perfdata/perfdata_test.go b/pkg/perfdata/perfdata_test.go new file mode 100644 index 0000000..c6df024 --- /dev/null +++ b/pkg/perfdata/perfdata_test.go @@ -0,0 +1,138 @@ +package perfdata + +import "testing" + +func TestCreatePerformanceData(t *testing.T) { + pd := CreatePerformanceData("testing", 123.43, "") + want := "| 'testing'=123.430000;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 123.43, "s") + want = "| 'testing'=123.430000s;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 123.43, "us") + want = "| 'testing'=123.430000us;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 123.43, "ms") + want = "| 'testing'=123.430000ms;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 99.43, "%") + want = "| 'testing'=99.430000%;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 123.43, "B") + want = "| 'testing'=123.430000B;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 123.43, "KB") + want = "| 'testing'=123.430000KB;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 123.43, "MB") + want = "| 'testing'=123.430000MB;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 123.43, "TB") + want = "| 'testing'=123.430000TB;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } + + pd = CreatePerformanceData("testing", 123.43, "c") + want = "| 'testing'=123.430000c;;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } +} + +func TestSetWarning(t *testing.T) { + pd := CreatePerformanceData("testing", 123.43, "") + + pd.SetWarning(62) + + want := "| 'testing'=123.430000;62.000000;;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } +} + +func TestSetCritical(t *testing.T) { + pd := CreatePerformanceData("testing", 123.43, "") + + pd.SetCritical(62) + + want := "| 'testing'=123.430000;;62.000000;;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } +} + +func TestSetMinimum(t *testing.T) { + pd := CreatePerformanceData("testing", 123.43, "") + + pd.SetMinimum(62) + + want := "| 'testing'=123.430000;;;62.000000;" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } +} + +func TestSetMaximum(t *testing.T) { + pd := CreatePerformanceData("testing", 123.43, "") + + pd.SetMaximum(62) + + want := "| 'testing'=123.430000;;;;62.000000" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } +} + +func TestGetPerformanceDataAsString(t *testing.T) { + pd := CreatePerformanceData("testing", 123.43, "s") + + pd.SetWarning(48) + pd.SetCritical(55) + pd.SetMinimum(13) + pd.SetMaximum(875) + + want := "| 'testing'=123.430000s;48.000000;55.000000;13.000000;875.000000" + + if pd.GetPerformanceDataAsString() != want { + t.Errorf("CreatePerformanceData was incorrect, got: %s, want: %s.", pd.GetPerformanceDataAsString(), want) + } +} diff --git a/pkg/thresholds/thresholds.go b/pkg/thresholds/thresholds.go index 22b2101..51aa8d1 100644 --- a/pkg/thresholds/thresholds.go +++ b/pkg/thresholds/thresholds.go @@ -1,5 +1,14 @@ package thresholds +// GetThresholdsStatus returns true if thresholds are set otherwise false +func GetThresholdsStatus(threshold float64) bool { + if threshold == -1.0 { + return false + } + + return true +} + // CheckLower checks if val is lower than threshold func CheckLower(threshold float64, val float64) bool { if threshold == -1.0 {