diff --git a/examples/check_example2/main.go b/examples/check_example2/main.go index ba23761..2d8ef44 100644 --- a/examples/check_example2/main.go +++ b/examples/check_example2/main.go @@ -20,10 +20,12 @@ func main() { check.ExitError(err) } - check1.Perfdata.Add(&perfdata.Perfdata{ + pd := &perfdata.Perfdata{ Label: "foo", - Value: 23, - }) + Value: perfdata.NewPdvUint64(23), + } + + check1.Perfdata.Add(pd) check2 := result.PartialResult{} @@ -34,14 +36,17 @@ func main() { check.ExitError(err) } - check2.Perfdata.Add(&perfdata.Perfdata{ + pd2 := &perfdata.Perfdata{ Label: "bar", - Value: 42, - }) - check2.Perfdata.Add(&perfdata.Perfdata{ + Value: perfdata.NewPdvUint64(42), + } + check2.Perfdata.Add(pd2) + + pd3 := &perfdata.Perfdata{ Label: "foo2 bar", - Value: 46, - }) + Value: perfdata.NewPdvUint64(46), + } + check2.Perfdata.Add(pd3) overall.AddSubcheck(check1) overall.AddSubcheck(check2) diff --git a/perfdata/list_test.go b/perfdata/list_test.go index 57e3c9a..ed631b7 100644 --- a/perfdata/list_test.go +++ b/perfdata/list_test.go @@ -9,8 +9,8 @@ import ( func ExamplePerfdataList() { list := PerfdataList{} - list.Add(&Perfdata{Label: "test1", Value: 23}) - list.Add(&Perfdata{Label: "test2", Value: 42}) + list.Add(&Perfdata{Label: "test1", Value: NewPdvUint64(23)}) + list.Add(&Perfdata{Label: "test2", Value: NewPdvUint64(42)}) fmt.Println(list) @@ -20,8 +20,8 @@ func ExamplePerfdataList() { func TestPerfdataListFormating(t *testing.T) { list := PerfdataList{} - list.Add(&Perfdata{Label: "test1", Value: 23}) - list.Add(&Perfdata{Label: "test2", Value: 42}) + list.Add(&Perfdata{Label: "test1", Value: NewPdvUint64(23)}) + list.Add(&Perfdata{Label: "test2", Value: NewPdvUint64(42)}) assert.Equal(t, "test1=23 test2=42", list.String()) } @@ -30,8 +30,8 @@ func BenchmarkPerfdataListFormating(b *testing.B) { b.ReportAllocs() list := PerfdataList{} - list.Add(&Perfdata{Label: "test1", Value: 23}) - list.Add(&Perfdata{Label: "test2", Value: 42}) + list.Add(&Perfdata{Label: "test1", Value: NewPdvUint64(23)}) + list.Add(&Perfdata{Label: "test2", Value: NewPdvUint64(42)}) for i := 0; i < b.N; i++ { l := list.String() diff --git a/perfdata/type.go b/perfdata/type.go index dc9202e..3f326fc 100644 --- a/perfdata/type.go +++ b/perfdata/type.go @@ -2,8 +2,8 @@ package perfdata import ( "errors" - "fmt" "math" + "strconv" "strings" "github.com/NETWAYS/go-check" @@ -19,32 +19,26 @@ var replacer = strings.NewReplacer("=", "_", "`", "_", "'", "_", "\"", "_") // represent a valid measurement, e.g INF for floats // This error can probably ignored in most cases and the perfdata point omitted, // but silently dropping the value and returning the empty strings seems like bad style -func formatNumeric(value interface{}) (string, error) { - switch v := value.(type) { - case float64: - if math.IsInf(v, 0) { - return "", errors.New("Perfdata value is inifinite") +func formatNumeric(value Value) (string, error) { + switch value.kind { + case floatType: + if math.IsInf(value.floatVal, 0) { + return "", errors.New("perfdata value is inifinite") } - if math.IsNaN(v) { - return "", errors.New("Perfdata value is inifinite") + if math.IsNaN(value.floatVal) { + return "", errors.New("perfdata value is NaN") } - return check.FormatFloat(v), nil - case float32: - if math.IsInf(float64(v), 0) { - return "", errors.New("Perfdata value is inifinite") - } - - if math.IsNaN(float64(v)) { - return "", errors.New("Perfdata value is inifinite") - } - - return check.FormatFloat(float64(v)), nil - case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: - return fmt.Sprintf("%d", v), nil + return check.FormatFloat(value.floatVal), nil + case intType: + return strconv.FormatInt(value.intVal, 10), nil + case uintType: + return strconv.FormatUint(value.uintVal, 10), nil + case noneType: + return "", errors.New("value was not set") default: - panic(fmt.Sprintf("unsupported type for perfdata: %T", value)) + return "", errors.New("this should not happen") } } @@ -61,13 +55,50 @@ func formatNumeric(value interface{}) (string, error) { // https://icinga.com/docs/icinga-2/latest/doc/05-service-monitoring/#unit-of-measurement-uom type Perfdata struct { Label string - Value interface{} + Value Value // Uom is the unit-of-measurement, see links above for details. Uom string Warn *check.Threshold Crit *check.Threshold - Min interface{} - Max interface{} + Min Value + Max Value +} + +type perfdataValueTypeEnum int + +const ( + noneType perfdataValueTypeEnum = iota + intType + uintType + floatType +) + +type Value struct { + kind perfdataValueTypeEnum + uintVal uint64 + intVal int64 + floatVal float64 +} + +func NewPdvUint64(val uint64) Value { + return Value{ + kind: uintType, + uintVal: val, + } +} + +func NewPdvInt64(val int64) Value { + return Value{ + kind: intType, + intVal: val, + } +} + +func NewPdvFloat64(val float64) Value { + return Value{ + kind: floatType, + floatVal: val, + } } // String returns the proper format for the plugin output @@ -109,10 +140,10 @@ func (p Perfdata) ValidatedString() (string, error) { } // Limits - for _, value := range []interface{}{p.Min, p.Max} { + for _, value := range []Value{p.Min, p.Max} { sb.WriteString(";") - if value != nil { + if value.kind != noneType { pfVal, err := formatNumeric(value) // Attention: we ignore limits if they are faulty if err == nil { diff --git a/perfdata/type_test.go b/perfdata/type_test.go index 5eff5e3..0bebafa 100644 --- a/perfdata/type_test.go +++ b/perfdata/type_test.go @@ -13,12 +13,12 @@ func BenchmarkPerfdataString(b *testing.B) { perf := Perfdata{ Label: "test test=test", - Value: 10.1, + Value: NewPdvFloat64(10.1), Uom: "%", Warn: &check.Threshold{Upper: 80}, Crit: &check.Threshold{Upper: 90}, - Min: 0, - Max: 100} + Min: NewPdvUint64(0), + Max: NewPdvInt64(100)} for i := 0; i < b.N; i++ { p := perf.String() @@ -34,28 +34,28 @@ func TestRenderPerfdata(t *testing.T) { "simple": { perf: Perfdata{ Label: "test", - Value: 2, + Value: NewPdvUint64(2), }, expected: "test=2", }, "with-quotes": { perf: Perfdata{ Label: "te's\"t", - Value: 2, + Value: NewPdvInt64(2), }, expected: "te_s_t=2", }, "with-special-chars": { perf: Perfdata{ Label: "test_🖥️_'test", - Value: 2, + Value: NewPdvUint64(2), }, expected: "test_🖥️__test=2", }, "with-uom": { perf: Perfdata{ Label: "test", - Value: 2, + Value: NewPdvInt64(2), Uom: "%", }, expected: "test=2%", @@ -63,7 +63,7 @@ func TestRenderPerfdata(t *testing.T) { "with-thresholds": { perf: Perfdata{ Label: "foo bar", - Value: 2.76, + Value: NewPdvFloat64(2.76), Uom: "m", Warn: &check.Threshold{Lower: 10, Upper: 25, Inside: true}, Crit: &check.Threshold{Lower: 15, Upper: 20, Inside: false}, @@ -79,7 +79,7 @@ func TestRenderPerfdata(t *testing.T) { "invalid-value": { perf: Perfdata{ Label: "to infinity", - Value: math.Inf(+1), + Value: NewPdvFloat64(math.Inf(+1)), }, expected: "", }, @@ -104,34 +104,34 @@ func TestRenderPerfdata(t *testing.T) { type pfFormatTest struct { Result string - InputValue interface{} + InputValue Value } func TestFormatNumeric(t *testing.T) { testdata := []pfFormatTest{ { Result: "10", - InputValue: 10, + InputValue: NewPdvUint64(10), }, { Result: "-10", - InputValue: -10, + InputValue: NewPdvInt64(-10), }, { Result: "10", - InputValue: uint8(10), + InputValue: NewPdvUint64(10), }, { Result: "1234.567", - InputValue: float64(1234.567), + InputValue: NewPdvFloat64(1234.567), }, { Result: "3456.789", - InputValue: float32(3456.789), + InputValue: NewPdvFloat64(3456.789), }, { Result: "1234567890.988", - InputValue: 1234567890.9877, + InputValue: NewPdvFloat64(1234567890.9877), }, } diff --git a/result/overall.go b/result/overall.go index cb58991..9827ab4 100644 --- a/result/overall.go +++ b/result/overall.go @@ -98,53 +98,53 @@ func (o *Overall) GetStatus() int { return check.Warning } else if o.oks > 0 { return check.OK - } else { - return check.Unknown - } - } else { - // state not set explicitly! - if len(o.PartialResults) == 0 { - return check.Unknown } - var ( - criticals int - warnings int - oks int - unknowns int - ) + return check.Unknown + } - for _, sc := range o.PartialResults { - switch sc.GetStatus() { - case check.Critical: - criticals++ - case check.Warning: - warnings++ - case check.Unknown: - unknowns++ - case check.OK: - oks++ - } - } + // state not set explicitly! + if len(o.PartialResults) == 0 { + return check.Unknown + } - if criticals > 0 { - return check.Critical + var ( + criticals int + warnings int + oks int + unknowns int + ) + + for _, sc := range o.PartialResults { + switch sc.GetStatus() { + case check.Critical: + criticals++ + case check.Warning: + warnings++ + case check.Unknown: + unknowns++ + case check.OK: + oks++ } + } - if unknowns > 0 { - return check.Unknown - } + if criticals > 0 { + return check.Critical + } - if warnings > 0 { - return check.Warning - } + if unknowns > 0 { + return check.Unknown + } - if oks > 0 { - return check.OK - } + if warnings > 0 { + return check.Warning + } - return check.Unknown + if oks > 0 { + return check.OK } + + return check.Unknown } // GetSummary returns a text representation of the current state of the Overall diff --git a/result/overall_test.go b/result/overall_test.go index ab84109..2958955 100644 --- a/result/overall_test.go +++ b/result/overall_test.go @@ -139,7 +139,7 @@ func ExampleOverall_GetStatus() { func ExampleOverall_withSubchecks() { var overall Overall - example_perfdata := perfdata.Perfdata{Label: "pd_test", Value: 5, Uom: "s"} + example_perfdata := perfdata.Perfdata{Label: "pd_test", Value: perfdata.NewPdvUint64(5), Uom: "s"} pd_list := perfdata.PerfdataList{} pd_list.Add(&example_perfdata) @@ -164,17 +164,17 @@ func ExampleOverall_withSubchecks() { func TestOverall_withEnhancedSubchecks(t *testing.T) { var overall Overall - example_perfdata := perfdata.Perfdata{Label: "pd_test", Value: 5, Uom: "s"} + example_perfdata := perfdata.Perfdata{Label: "pd_test", Value: perfdata.NewPdvUint64(5), Uom: "s"} example_perfdata2 := perfdata.Perfdata{ Label: "pd_test2", - Value: 1099511627776, + Value: perfdata.NewPdvUint64(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), + Max: perfdata.NewPdvUint64((18446744073709551615)), } - example_perfdata3 := perfdata.Perfdata{Label: "kl;jr2if;l2rkjasdf", Value: 5, Uom: "m"} - example_perfdata4 := perfdata.Perfdata{Label: "asdf", Value: uint64(18446744073709551615), Uom: "B"} + example_perfdata3 := perfdata.Perfdata{Label: "kl;jr2if;l2rkjasdf", Value: perfdata.NewPdvUint64(5), Uom: "m"} + example_perfdata4 := perfdata.Perfdata{Label: "asdf", Value: perfdata.NewPdvUint64(18446744073709551615), Uom: "B"} pd_list := perfdata.PerfdataList{} pd_list.Add(&example_perfdata) @@ -259,11 +259,11 @@ func TestOverall_withSubchecks_Perfdata(t *testing.T) { perf1 := perfdata.Perfdata{ Label: "foo", - Value: 3, + Value: perfdata.NewPdvUint64(3), } perf2 := perfdata.Perfdata{ Label: "bar", - Value: 300, + Value: perfdata.NewPdvUint64(300), Uom: "%", } @@ -302,16 +302,16 @@ func TestOverall_withSubchecks_PartialResult(t *testing.T) { perf1 := perfdata.Perfdata{ Label: "foo", - Value: 3, + Value: perfdata.NewPdvUint64(3), } perf2 := perfdata.Perfdata{ Label: "bar", - Value: 300, + Value: perfdata.NewPdvUint64(300), Uom: "%", } perf3 := perfdata.Perfdata{ Label: "baz", - Value: 23, + Value: perfdata.NewPdvUint64(23), Uom: "B", } @@ -376,11 +376,11 @@ func TestSubchecksPerfdata(t *testing.T) { Perfdata: perfdata.PerfdataList{ &perfdata.Perfdata{ Label: "foo", - Value: 23, + Value: perfdata.NewPdvUint64(23), }, &perfdata.Perfdata{ Label: "bar", - Value: 42, + Value: perfdata.NewPdvUint64(42), }, }, } @@ -392,7 +392,7 @@ func TestSubchecksPerfdata(t *testing.T) { Perfdata: perfdata.PerfdataList{ &perfdata.Perfdata{ Label: "foo2 bar", - Value: 46, + Value: perfdata.NewPdvUint64(46), }, }, }