Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion perfdata/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

// Lists all allowed characters inside a label, so we can replace any non-matching
var validInLabelRe = regexp.MustCompile(`[^a-zA-Z0-9 _\-+:/.]+`)
var validInLabelRe = regexp.MustCompile(`[^a-zA-Z0-9 _\-+:/.;]+`)

// FormatNumeric returns a string representation of various possible numerics
//
Expand Down
84 changes: 82 additions & 2 deletions result/overall.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,54 @@ package result
import (
"fmt"
"github.com/NETWAYS/go-check"
"github.com/NETWAYS/go-check/perfdata"
"strings"
)

// So, this is the idea:
// A check plugin has a single Overall (singleton)
// Each partial thing which is tested, gets it's own subcheck
// The results of these may be relevant to the overall status in the end
// or not, e.g. if a plugin trieds two different methods for something and
// one suffices, but one fails, the whole check might be OK and only the subcheck
// Warning or Critical.
type Overall struct {
OKs int
Warnings int
Criticals int
Unknowns int
Summary string
Outputs []string
Outputs []string // Deprecate this in a future version
partialResults []PartialResult
}

type PartialResult struct {
State int
Output string
Perfdata perfdata.PerfdataList
partialResults []PartialResult
}

func (s *PartialResult) String() string {
return fmt.Sprintf("[%s] %s|%s", check.StatusText(s.State), s.Output, s.Perfdata.String())
}

// Deprecate this in a future version
func (o *Overall) AddOK(output string) {
o.Add(check.OK, output)
}

// Deprecate this in a future version
func (o *Overall) AddWarning(output string) {
o.Add(check.Warning, output)
}

// Deprecate this in a future version
func (o *Overall) AddCritical(output string) {
o.Add(check.Critical, output)
}

// Deprecate this in a future version
func (o *Overall) AddUnknown(output string) {
o.Add(check.Unknown, output)
}
Expand All @@ -47,6 +71,14 @@ func (o *Overall) Add(state int, output string) {
o.Outputs = append(o.Outputs, fmt.Sprintf("[%s] %s", check.StatusText(state), output))
}

func (o *Overall) AddSubcheck(subcheck PartialResult) {
o.partialResults = append(o.partialResults, subcheck)
}

func (o *PartialResult) AddSubcheck(subcheck PartialResult) {
o.partialResults = append(o.partialResults, subcheck)
}

func (o *Overall) GetStatus() int {
if o.Criticals > 0 {
return check.Critical
Expand Down Expand Up @@ -79,9 +111,37 @@ func (o *Overall) GetSummary() string {
o.Summary += fmt.Sprintf("ok=%d ", o.OKs)
}

if o.Summary == "" {
if o.Summary == "" && len(o.partialResults) == 0 {
o.Summary = "No status information"
} else {
criticals := 0
warnings := 0
oks := 0
unknowns := 0
for _, sc := range o.partialResults {
if sc.State == check.Critical {
criticals++
} else if sc.State == check.Warning {
warnings++
} else if sc.State == check.Unknown {
unknowns++
} else if sc.State == check.OK {
oks++
}
}

if criticals > 0 {
o.Summary += fmt.Sprintf("critical=%d ", criticals)
}
if unknowns > 0 {
o.Summary += fmt.Sprintf("unknowns=%d ", unknowns)
}
if warnings > 0 {
o.Summary += fmt.Sprintf("warning=%d ", warnings)
}
if oks > 0 {
o.Summary += fmt.Sprintf("ok=%d ", oks)
}
o.Summary = "states: " + strings.TrimSpace(o.Summary)
}
}
Expand All @@ -96,6 +156,26 @@ func (o *Overall) GetOutput() string {
output += extra + "\n"
}

if o.partialResults != nil {
for _, s := range o.partialResults {
output += s.getOutput(0)
}
}

return output
}

func (s *PartialResult) getOutput(indent_level int) string {
var output string

prefix := strings.Repeat(" ", indent_level)
output += prefix + "\\_ " + s.String() + "\n"

if s.partialResults != nil {
for _, ss := range s.partialResults {
output += ss.getOutput(indent_level + 2)
}
}

return output
}
93 changes: 92 additions & 1 deletion result/overall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package result
import (
"fmt"
"github.com/NETWAYS/go-check"
"github.com/NETWAYS/go-check/perfdata"
"github.com/stretchr/testify/assert"
"testing"
)
Expand Down Expand Up @@ -90,7 +91,7 @@ func ExampleOverall_Add() {
overall.Add(check.Critical, "The other is critical")

fmt.Println(overall)
// Output: {1 0 1 0 [[OK] One element is good [CRITICAL] The other is critical]}
// Output: {1 0 1 0 [[OK] One element is good [CRITICAL] The other is critical] []}
}

func ExampleOverall_GetOutput() {
Expand All @@ -113,3 +114,93 @@ func ExampleOverall_GetStatus() {
fmt.Println(overall.GetStatus())
// Output: 2
}

func ExampleOverall_withSubchecks() {
var overall Overall

example_perfdata := perfdata.Perfdata{Label: "pd_test", Value: 5, Uom: "s"}
pd_list := perfdata.PerfdataList{}
pd_list.Add(&example_perfdata)

subcheck := PartialResult{
State: check.OK,
Output: "Subcheck1 Test",
Perfdata: pd_list,
}

overall.AddSubcheck(subcheck)
overall.AddOK("bla")

fmt.Println(overall.GetOutput())
// Output:
// states: ok=1 ok=1
// [OK] bla
// \_ [OK] Subcheck1 Test|pd_test=5s
}

//nolint
func ExampleOverall_withSubchecks2() {
var overall Overall

example_perfdata := perfdata.Perfdata{Label: "pd_test", Value: 5, Uom: "s"}
example_perfdata2 := perfdata.Perfdata{
Label: "pd_test2",
Value: 1099511627776,
Uom: "kB",
Warn: &check.Threshold{Inside: true, Lower: 3.14, Upper: 0x66666666666},
Crit: &check.Threshold{Inside: false, Lower: 07777777777777, Upper: 0xFFFFFFFFFFFFFFFFFFFF},
Max: uint64(18446744073709551615),
}
example_perfdata3 := perfdata.Perfdata{Label: "kl;jr2if;l2rkjasdf", Value: 5, Uom: "m"}
example_perfdata4 := perfdata.Perfdata{Label: "asdf", Value: uint64(18446744073709551615), Uom: "B"}

pd_list := perfdata.PerfdataList{}
pd_list.Add(&example_perfdata)
pd_list.Add(&example_perfdata2)

pd_list2 := perfdata.PerfdataList{}
pd_list2.Add(&example_perfdata3)
pd_list2.Add(&example_perfdata4)

subcheck := PartialResult{
State: check.OK,
Output: "Subcheck1 Test",
Perfdata: pd_list,
}
subcheck2 := PartialResult{
State: check.Warning,
Output: "Subcheck2 Test",
Perfdata: pd_list2,
}

overall.AddSubcheck(subcheck)
overall.AddSubcheck(subcheck2)

fmt.Println(overall.GetOutput())

// states: warning=1 ok=1
// \_ [OK] Subcheck1 Test|pd_test=5s pd_test2=1099511627776kB;@3.14:7036874417766;549755813887:1208925819614629174706176;;18446744073709551615
// \_ [WARNING] Subcheck2 Test|kl;jr2if;l2rkjasdf=5m asdf=18446744073709551615B
}

func ExampleOverall_withSubchecks3() {
var overall Overall

subcheck2 := PartialResult{
State: check.OK,
Output: "SubSubcheck",
}
subcheck := PartialResult{
State: check.OK,
Output: "PartialResult",
}
subcheck.partialResults = append(subcheck.partialResults, subcheck2)

overall.AddSubcheck(subcheck)

fmt.Println(overall.GetOutput())

// states: ok=1
// \_ [OK] PartialResult|
// \_ [OK] SubSubcheck|
}