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
17 changes: 11 additions & 6 deletions Exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ func ErrorExit(err error) {

// Exit returns with the given returncode and message and optional PerformanceData
func Exit(state State, msg string) {
LongExit(state, msg, "")
LongExit(state, msg, "", nil)
}

// LongExit returns with the given returncode and message and optional PerformanceData and long message
func LongExit(state State, msg, longMsg string) {
if perf := PrintPerformanceData(); perf == "" {
fmt.Printf("%s - %s\n%s", state.name, msg, longMsg)
func LongExit(state State, msg, longMsg string, collection *PerformanceDataCollection) {
perfString := ""
if collection != nil {
perfString = collection.PrintAllPerformanceData()
}

if perfString == "" {
fmt.Printf("%s - %s\n%s", state.Name, msg, longMsg)
} else {
fmt.Printf("%s - %s|%s\n%s", state.name, msg, perf, longMsg)
fmt.Printf("%s - %s|%s\n%s", state.Name, msg, perfString, longMsg)
}
os.Exit(state.code)
os.Exit(state.Code)
}
166 changes: 120 additions & 46 deletions PerformanceData.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,68 +7,123 @@ import (
"sync"
)

type PerformanceData map[string]interface{}
// PerformanceData is a map with string keys and any values, essentially a dictionary
// Since its an dictionary, always add add a label
// "label" = "health_rate"
// "value" = 80
// "critical" = 160
type PerformanceData map[string]any

var (
p []PerformanceData = []PerformanceData{}
pMutex = &sync.Mutex{}
)
// This is a struct that users of the library should use.
// They have to manage this object through functions in this file
// Library clients should get an instance of this and keep calling its methods
type PerformanceDataCollection struct {
data []PerformanceData
dataMutex *sync.Mutex
}

// Returns an empty PerformanceDataCollection
func NewPerformanceDataCollection() PerformanceDataCollection {
return PerformanceDataCollection{
data: make([]PerformanceData, 0),
dataMutex: &sync.Mutex{},
}
}

// NewPerformanceData adds a PerformanceData object which can be expanded with further information
func NewPerformanceData(label string, value float64) *PerformanceData {
return NewPerformanceDataString(label, strconv.FormatFloat(value, 'f', -1, 64))
// Adds a new PerformanceData element to the data array
// Use the label to get the reference to the PerformanceData later on
func (collection *PerformanceDataCollection) AddPerformanceData(label string, value string) {
collection.dataMutex.Lock()
collection.data = append(collection.data, PerformanceData{"label": label, "value": value})
collection.dataMutex.Unlock()
}

// NewPerformanceDataString adds a PerformanceData object which can be expanded with further information
func NewPerformanceDataString(label, value string) *PerformanceData {
pMutex.Lock()
p = append(p, PerformanceData{"label": label, "value": value})
newOne := &(p[len(p)-1])
pMutex.Unlock()
return newOne
// Calls collection.AddPerformanceData after converting float to string
func (collection *PerformanceDataCollection) AddPerformanceDataFloat64(label string, value float64) {
collection.AddPerformanceData(label, strconv.FormatFloat(value, 'f', -1, 64))
}

// Unit adds an unit string to the PerformanceData
func (p PerformanceData) Unit(unit string) PerformanceData {
p["unit"] = unit
return p
// Internal function to find a PerformanceData with specified label
func (collection *PerformanceDataCollection) findPerformanceData(label string) (*PerformanceData, error) {
for index, pd := range collection.data {
if pd_label, ok := pd["label"]; ok && pd_label == label {
return &collection.data[index], nil
}
}
return nil, fmt.Errorf("no performance data with the label '%s' found", label)
}

// Adds a field called "unit" to the PerformanceData with the label
func (collection *PerformanceDataCollection) Unit(label string, unit string) error {
collection.dataMutex.Lock()
defer collection.dataMutex.Unlock()
pd, err := collection.findPerformanceData(label)
if err != nil {
return err
}
(*pd)["unit"] = unit
return nil
}

// Warn adds the threshold to the PerformanceData
func (p PerformanceData) Warn(warn *Threshold) PerformanceData {
p["warn"] = warn
return p
// Adds a field called "unit" to the PerformanceData with the label
func (collection *PerformanceDataCollection) Warn(label string, warn *Threshold) error {
collection.dataMutex.Lock()
defer collection.dataMutex.Unlock()
pd, err := collection.findPerformanceData(label)
if err != nil {
return err
}
(*pd)["warn"] = warn
return nil
}

// Crit adds the threshold to the PerformanceData
func (p PerformanceData) Crit(crit *Threshold) PerformanceData {
p["crit"] = crit
return p
// Adds a field called "unit" to the PerformanceData with the label
func (collection *PerformanceDataCollection) Crit(label string, crit *Threshold) error {
collection.dataMutex.Lock()
defer collection.dataMutex.Unlock()
pd, err := collection.findPerformanceData(label)
if err != nil {
return err
}
(*pd)["crit"] = crit
return nil
}

// Min adds the float64 to the PerformanceData
func (p PerformanceData) Min(min float64) PerformanceData {
p["min"] = min
return p
// Adds a field called "unit" to the PerformanceData with the label
func (collection *PerformanceDataCollection) Min(label string, min float64) error {
collection.dataMutex.Lock()
defer collection.dataMutex.Unlock()
pd, err := collection.findPerformanceData(label)
if err != nil {
return err
}
(*pd)["min"] = min
return nil
}

// Min adds the float64 to the PerformanceData
func (p PerformanceData) Max(max float64) PerformanceData {
p["max"] = max
return p
// Adds a field called "unit" to the PerformanceData with the label
func (collection *PerformanceDataCollection) Max(label string, max float64) error {
collection.dataMutex.Lock()
defer collection.dataMutex.Unlock()
pd, err := collection.findPerformanceData(label)
if err != nil {
return err
}
(*pd)["max"] = max
return nil
}

// toString prints this PerformanceData
func (p PerformanceData) toString() string {
// internal function to print a PerformanceData
func (pd PerformanceData) toString() string {
var toPrint bytes.Buffer

toPrint.WriteString(fmt.Sprintf("'%s'=%s", p["label"], p["value"]))
if unit, ok := p["unit"]; ok {
toPrint.WriteString(fmt.Sprintf("'%s'=%s", pd["label"], pd["value"]))
if unit, ok := pd["unit"]; ok {
toPrint.WriteString(unit.(string))
}
toPrint.WriteString(";")
addThreshold := func(key string) {
if value, ok := p[key]; ok && value != nil {
if value, ok := pd[key]; ok && value != nil {
if t := value.(*Threshold); t != nil {
toPrint.WriteString(t.input)
}
Expand All @@ -79,7 +134,7 @@ func (p PerformanceData) toString() string {
addThreshold("crit")

addFloat := func(key string) {
if value, ok := p[key]; ok {
if value, ok := pd[key]; ok {
toPrint.WriteString(strconv.FormatFloat(value.(float64), 'f', -1, 64))
}
}
Expand All @@ -90,14 +145,33 @@ func (p PerformanceData) toString() string {
return toPrint.String()
}

// PrintPerformanceData prints all PerformanceData
func PrintPerformanceData() string {
// Finds and prints the PerformanceData found in this collection
func (collection *PerformanceDataCollection) PrintPerformanceData(label string) (string, error) {
collection.dataMutex.Lock()
defer collection.dataMutex.Unlock()
pd, err := collection.findPerformanceData(label)
if err != nil {
return "", err
}

return (*pd).toString(), nil
}

// Prints all PerformanceData to a string in this collection
func (collection *PerformanceDataCollection) PrintAllPerformanceData() string {
collection.dataMutex.Lock()
defer collection.dataMutex.Unlock()
var toPrint bytes.Buffer
pMutex.Lock()
for _, perfData := range p {
for _, perfData := range collection.data {
toPrint.WriteString(perfData.toString())
toPrint.WriteString(" ")
}
pMutex.Unlock()
return toPrint.String()
}

// Clears all PerformanceData stored in this collection
func (collection *PerformanceDataCollection) ClearPerformanceCollection() {
collection.dataMutex.Lock()
defer collection.dataMutex.Unlock()
collection.data = make([]PerformanceData, 0)
}
109 changes: 78 additions & 31 deletions PerformanceData_test.go
Original file line number Diff line number Diff line change
@@ -1,76 +1,123 @@
package check_x

import (
"reflect"
"testing"
)

var perfdataToString = []struct {
f func() PerformanceData
f func() PerformanceDataCollection
expected string
}{
{func() PerformanceData {
return *NewPerformanceDataString("a", "1")
{func() PerformanceDataCollection {
col := NewPerformanceDataCollection()
col.AddPerformanceData("a", "1")
return col
}, "'a'=1;;;;"},
{func() PerformanceData {
{func() PerformanceDataCollection {
warn, _ := NewThreshold("10:")
return NewPerformanceDataString("a", "2").Warn(warn)
col := NewPerformanceDataCollection()
col.AddPerformanceData("a", "2")
col.Warn("a", warn)
return col
}, "'a'=2;10:;;;"},
{func() PerformanceData {
{func() PerformanceDataCollection {
warn, _ := NewThreshold("10:")
crit, _ := NewThreshold("@10:20")
return NewPerformanceDataString("a", "3").Warn(warn).Crit(crit)
col := NewPerformanceDataCollection()
col.AddPerformanceData("a", "3")
col.Warn("a", warn)
col.Crit("a", crit)
return col
}, "'a'=3;10:;@10:20;;"},
{func() PerformanceData {
{func() PerformanceDataCollection {
warn, _ := NewThreshold("10:")
crit, _ := NewThreshold("@10:20")
return NewPerformanceDataString("a", "3").Warn(warn).Crit(crit).Min(0)
col := NewPerformanceDataCollection()
col.AddPerformanceData("a", "3")
col.Warn("a", warn)
col.Crit("a", crit)
col.Min("a", 0)
return col
}, "'a'=3;10:;@10:20;0;"},
{func() PerformanceData {
{func() PerformanceDataCollection {
warn, _ := NewThreshold("10:")
crit, _ := NewThreshold("@10:20")
return NewPerformanceDataString("a", "4").Warn(warn).Crit(crit).Min(0).Max(100)
col := NewPerformanceDataCollection()
col.AddPerformanceData("a", "4")
col.Warn("a", warn)
col.Crit("a", crit)
col.Min("a", 0)
col.Max("a", 100)
return col
}, "'a'=4;10:;@10:20;0;100"},
{func() PerformanceData {
{func() PerformanceDataCollection {
warn, _ := NewThreshold("10:")
crit, _ := NewThreshold("@10:20")
return NewPerformanceDataString("a", "5").Warn(warn).Crit(crit).Min(0).Max(100).Unit("C")
col := NewPerformanceDataCollection()
col.AddPerformanceData("a", "5")
col.Warn("a", warn)
col.Crit("a", crit)
col.Min("a", 0)
col.Max("a", 100)
col.Unit("a", "C")
return col
}, "'a'=5C;10:;@10:20;0;100"},
{func() PerformanceData {
{func() PerformanceDataCollection {
warn, _ := NewThreshold("10:")
crit, _ := NewThreshold("@10:20")
return NewPerformanceData("a", 6).Warn(warn).Crit(crit).Min(0).Max(100).Unit("C")
col := NewPerformanceDataCollection()
col.AddPerformanceDataFloat64("a", 6)
col.Warn("a", warn)
col.Crit("a", crit)
col.Min("a", 0)
col.Max("a", 100)
col.Unit("a", "C")
return col
}, "'a'=6C;10:;@10:20;0;100"},
{func() PerformanceData {
{func() PerformanceDataCollection {
warn, _ := NewThreshold("")
crit, _ := NewThreshold("@10:20")
return NewPerformanceData("a", 6).Warn(warn).Crit(crit).Min(0).Max(100).Unit("C")
col := NewPerformanceDataCollection()
col.AddPerformanceDataFloat64("a", 6)
col.Warn("a", warn)
col.Crit("a", crit)
col.Min("a", 0)
col.Max("a", 100)
col.Unit("a", "C")
return col
}, "'a'=6C;;@10:20;0;100"},
{func() PerformanceData {
{func() PerformanceDataCollection {
crit, _ := NewThreshold("@10:20")
return NewPerformanceData("a", 6).Warn(nil).Crit(crit).Min(0).Max(100).Unit("C")
col := NewPerformanceDataCollection()
col.AddPerformanceDataFloat64("a", 6)
col.Warn("a", nil)
col.Crit("a", crit)
col.Min("a", 0)
col.Max("a", 100)
col.Unit("a", "C")
return col
}, "'a'=6C;;@10:20;0;100"},
}

func TestPerformanceData_toString(t *testing.T) {
for i, data := range perfdataToString {
result := data.f()
resultString := result.toString()
if resultString != data.expected {
t.Errorf("%d - Expected: %s, got: %s", i, data.expected, resultString)
collection := data.f()
collectionString, err := collection.PrintPerformanceData("a")
if err != nil {
t.Errorf("Error when finding the performance data: %s", err.Error())
}
if !reflect.DeepEqual(p[i], result) {
t.Errorf("%d - Expected: %s, got: %s", i, p[i], result)
if collectionString != data.expected {
t.Errorf("%d - Expected: %s, got: %s", i, data.expected, collectionString)
}
}
}

func TestPrintPerformanceData(t *testing.T) {
p = []PerformanceData{}
NewPerformanceDataString("a", "1")
NewPerformanceDataString("b", "2")
col := NewPerformanceDataCollection()
col.AddPerformanceData("a", "1")
col.AddPerformanceData("b", "2")
expected := "'a'=1;;;;" + " " + "'b'=2;;;; "
if expected != PrintPerformanceData() {
t.Errorf("Expected: %s, got: %s", expected, PrintPerformanceData())
if expected != col.PrintAllPerformanceData() {
t.Errorf("Expected: %s, got: %s", expected, col.PrintAllPerformanceData())
}
}
Loading