1
1
package perfdata
2
2
3
3
import (
4
+ "errors"
4
5
"fmt"
6
+ "math"
5
7
"strings"
6
8
7
9
"github.com/NETWAYS/go-check"
@@ -13,16 +15,36 @@ var replacer = strings.NewReplacer("=", "_", "`", "_", "'", "_", "\"", "_")
13
15
// formatNumeric returns a string representation of various possible numerics
14
16
//
15
17
// This supports most internal types of Go and all fmt.Stringer interfaces.
16
- func formatNumeric (value interface {}) string {
18
+ // Returns an eror in some known cases where the value of a data type does not
19
+ // represent a valid measurement, e.g INF for floats
20
+ // This error can probably ignored in most cases and the perfdata point omitted,
21
+ // but silently dropping the value and returning the empty strings seems like bad style
22
+ func formatNumeric (value interface {}) (string , error ) {
17
23
switch v := value .(type ) {
18
24
case float64 :
19
- return check .FormatFloat (v )
25
+ if math .IsInf (v , 0 ) {
26
+ return "" , errors .New ("Perfdata value is inifinite" )
27
+ }
28
+
29
+ if math .IsNaN (v ) {
30
+ return "" , errors .New ("Perfdata value is inifinite" )
31
+ }
32
+
33
+ return check .FormatFloat (v ), nil
20
34
case float32 :
21
- return check .FormatFloat (float64 (v ))
35
+ if math .IsInf (float64 (v ), 0 ) {
36
+ return "" , errors .New ("Perfdata value is inifinite" )
37
+ }
38
+
39
+ if math .IsNaN (float64 (v )) {
40
+ return "" , errors .New ("Perfdata value is inifinite" )
41
+ }
42
+
43
+ return check .FormatFloat (float64 (v )), nil
22
44
case int , int8 , int16 , int32 , int64 , uint , uint8 , uint16 , uint32 , uint64 :
23
- return fmt .Sprintf ("%d" , v )
45
+ return fmt .Sprintf ("%d" , v ), nil
24
46
case fmt.Stringer , string :
25
- return fmt .Sprint (v )
47
+ return fmt .Sprint (v ), nil
26
48
default :
27
49
panic (fmt .Sprintf ("unsupported type for perfdata: %T" , value ))
28
50
}
@@ -51,7 +73,17 @@ type Perfdata struct {
51
73
}
52
74
53
75
// String returns the proper format for the plugin output
76
+ // on errors (occurs with invalid data, the empty string is returned
54
77
func (p Perfdata ) String () string {
78
+ tmp , _ := p .ValidatedString ()
79
+ return tmp
80
+ }
81
+
82
+ // ValidatedString returns the proper format for the plugin output
83
+ // Returns an eror in some known cases where the value of a data type does not
84
+ // represent a valid measurement, see the explanation for "formatNumeric" for
85
+ // perfdata values.
86
+ func (p Perfdata ) ValidatedString () (string , error ) {
55
87
var sb strings.Builder
56
88
57
89
// Add quotes if string contains any whitespace
@@ -61,7 +93,12 @@ func (p Perfdata) String() string {
61
93
sb .WriteString (replacer .Replace (p .Label ) + "=" )
62
94
}
63
95
64
- sb .WriteString (formatNumeric (p .Value ))
96
+ pfVal , err := formatNumeric (p .Value )
97
+ if err != nil {
98
+ return "" , err
99
+ }
100
+
101
+ sb .WriteString (pfVal )
65
102
sb .WriteString (p .Uom )
66
103
67
104
// Thresholds
@@ -78,9 +115,13 @@ func (p Perfdata) String() string {
78
115
sb .WriteString (";" )
79
116
80
117
if value != nil {
81
- sb .WriteString (formatNumeric (value ))
118
+ pfVal , err := formatNumeric (value )
119
+ // Attention: we ignore limits if they are faulty
120
+ if err == nil {
121
+ sb .WriteString (pfVal )
122
+ }
82
123
}
83
124
}
84
125
85
- return strings .TrimRight (sb .String (), ";" )
126
+ return strings .TrimRight (sb .String (), ";" ), nil
86
127
}
0 commit comments