summaryrefslogtreecommitdiff
path: root/utilities/utilities.go
diff options
context:
space:
mode:
authorWill Hawkins <[email protected]>2022-07-16 04:08:42 -0400
committerWill Hawkins <[email protected]>2022-07-16 04:08:42 -0400
commit23d16686f2320f9a5fe35aebbaa2e036b27421ca (patch)
treec5e5d097f68fb9e7cfe2e3c794cfad4bc3266adb /utilities/utilities.go
parentf0a9f4a3a50b63127a5e3d4ab2bdda3bbe4d8d0d (diff)
[Feature] Support spec v2 (4/4); Add data logging
Besides work to complete the support for v2 of the RFC, this patch adds support for logging each of the probe results to a CSV file (--logger-filename).
Diffstat (limited to 'utilities/utilities.go')
-rw-r--r--utilities/utilities.go55
1 files changed, 55 insertions, 0 deletions
diff --git a/utilities/utilities.go b/utilities/utilities.go
index 7b96bef..d4303ec 100644
--- a/utilities/utilities.go
+++ b/utilities/utilities.go
@@ -20,6 +20,8 @@ import (
"math/rand"
"os"
"reflect"
+ "sort"
+ "strings"
"sync/atomic"
"time"
)
@@ -129,3 +131,56 @@ func Max(x, y uint64) uint64 {
}
return y
}
+
+func ChannelToSlice[S any](channel <-chan S) (slice []S) {
+ slice = make([]S, 0)
+ for element := range channel {
+ slice = append(slice, element)
+ }
+ return
+}
+
+func Fmap[S any, F any](elements []S, mapper func(S) F) []F {
+ result := make([]F, 0)
+ for _, s := range elements {
+ result = append(result, mapper(s))
+ }
+ return result
+}
+
+func CalculatePercentile[S float32 | int32 | float64 | int64](elements []S, percentile int) S {
+ sort.Slice(elements, func(a, b int) bool { return elements[a] < elements[b] })
+ elementsCount := len(elements)
+ percentileIdx := elementsCount * (percentile / 100)
+ return elements[percentileIdx]
+}
+
+func OrTimeout(f func(), timeout time.Duration) {
+ completeChannel := func() chan interface{} {
+ completed := make(chan interface{})
+ go func() {
+ // This idea taken from https://stackoverflow.com/a/32843750.
+ // Closing the channel will let the read of it proceed immediately.
+ // Making that operation a defer ensures that it will happen even if
+ // the function f panics during its execution.
+ defer close(completed)
+ f()
+ }()
+ return completed
+ }()
+ select {
+ case _ = <-completeChannel:
+ break
+ case _ = <-time.After(timeout):
+ break
+ }
+}
+
+func FilenameAppend(filename, appendage string) string {
+ pieces := strings.SplitN(filename, ".", 2)
+ result := pieces[0] + appendage
+ if len(pieces) > 1 {
+ result = result + "." + strings.Join(pieces[1:], ".")
+ }
+ return result
+}