|
@@ -27,7 +27,9 @@ import (
|
|
|
|
|
|
|
|
type DataPoint struct {
|
|
type DataPoint struct {
|
|
|
Timestamp int64
|
|
Timestamp int64
|
|
|
|
|
+ MinLatency time.Duration
|
|
|
AvgLatency time.Duration
|
|
AvgLatency time.Duration
|
|
|
|
|
+ MaxLatency time.Duration
|
|
|
ThroughPut int64
|
|
ThroughPut int64
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -38,6 +40,8 @@ func (t TimeSeries) Len() int { return len(t) }
|
|
|
func (t TimeSeries) Less(i, j int) bool { return t[i].Timestamp < t[j].Timestamp }
|
|
func (t TimeSeries) Less(i, j int) bool { return t[i].Timestamp < t[j].Timestamp }
|
|
|
|
|
|
|
|
type secondPoint struct {
|
|
type secondPoint struct {
|
|
|
|
|
+ minLatency time.Duration
|
|
|
|
|
+ maxLatency time.Duration
|
|
|
totalLatency time.Duration
|
|
totalLatency time.Duration
|
|
|
count int64
|
|
count int64
|
|
|
}
|
|
}
|
|
@@ -57,10 +61,14 @@ func (sp *secondPoints) Add(ts time.Time, lat time.Duration) {
|
|
|
|
|
|
|
|
tk := ts.Unix()
|
|
tk := ts.Unix()
|
|
|
if v, ok := sp.tm[tk]; !ok {
|
|
if v, ok := sp.tm[tk]; !ok {
|
|
|
- sp.tm[tk] = secondPoint{totalLatency: lat, count: 1}
|
|
|
|
|
|
|
+ sp.tm[tk] = secondPoint{minLatency: lat, maxLatency: lat, totalLatency: lat, count: 1}
|
|
|
} else {
|
|
} else {
|
|
|
|
|
+ if lat != time.Duration(0) {
|
|
|
|
|
+ v.minLatency = minDuration(v.minLatency, lat)
|
|
|
|
|
+ }
|
|
|
|
|
+ v.maxLatency = maxDuration(v.maxLatency, lat)
|
|
|
v.totalLatency += lat
|
|
v.totalLatency += lat
|
|
|
- v.count += 1
|
|
|
|
|
|
|
+ v.count++
|
|
|
sp.tm[tk] = v
|
|
sp.tm[tk] = v
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -98,7 +106,9 @@ func (sp *secondPoints) getTimeSeries() TimeSeries {
|
|
|
}
|
|
}
|
|
|
tslice[i] = DataPoint{
|
|
tslice[i] = DataPoint{
|
|
|
Timestamp: k,
|
|
Timestamp: k,
|
|
|
|
|
+ MinLatency: v.minLatency,
|
|
|
AvgLatency: lat,
|
|
AvgLatency: lat,
|
|
|
|
|
+ MaxLatency: v.maxLatency,
|
|
|
ThroughPut: v.count,
|
|
ThroughPut: v.count,
|
|
|
}
|
|
}
|
|
|
i++
|
|
i++
|
|
@@ -111,14 +121,16 @@ func (sp *secondPoints) getTimeSeries() TimeSeries {
|
|
|
func (ts TimeSeries) String() string {
|
|
func (ts TimeSeries) String() string {
|
|
|
buf := new(bytes.Buffer)
|
|
buf := new(bytes.Buffer)
|
|
|
wr := csv.NewWriter(buf)
|
|
wr := csv.NewWriter(buf)
|
|
|
- if err := wr.Write([]string{"UNIX-TS", "AVG-LATENCY-MS", "AVG-THROUGHPUT"}); err != nil {
|
|
|
|
|
|
|
+ if err := wr.Write([]string{"UNIX-SECOND", "MIN-LATENCY-MS", "AVG-LATENCY-MS", "MAX-LATENCY-MS", "AVG-THROUGHPUT"}); err != nil {
|
|
|
log.Fatal(err)
|
|
log.Fatal(err)
|
|
|
}
|
|
}
|
|
|
rows := [][]string{}
|
|
rows := [][]string{}
|
|
|
for i := range ts {
|
|
for i := range ts {
|
|
|
row := []string{
|
|
row := []string{
|
|
|
fmt.Sprintf("%d", ts[i].Timestamp),
|
|
fmt.Sprintf("%d", ts[i].Timestamp),
|
|
|
|
|
+ fmt.Sprintf("%s", ts[i].MinLatency),
|
|
|
fmt.Sprintf("%s", ts[i].AvgLatency),
|
|
fmt.Sprintf("%s", ts[i].AvgLatency),
|
|
|
|
|
+ fmt.Sprintf("%s", ts[i].MaxLatency),
|
|
|
fmt.Sprintf("%d", ts[i].ThroughPut),
|
|
fmt.Sprintf("%d", ts[i].ThroughPut),
|
|
|
}
|
|
}
|
|
|
rows = append(rows, row)
|
|
rows = append(rows, row)
|
|
@@ -132,3 +144,17 @@ func (ts TimeSeries) String() string {
|
|
|
}
|
|
}
|
|
|
return fmt.Sprintf("\nSample in one second (unix latency throughput):\n%s", buf.String())
|
|
return fmt.Sprintf("\nSample in one second (unix latency throughput):\n%s", buf.String())
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+func minDuration(a, b time.Duration) time.Duration {
|
|
|
|
|
+ if a < b {
|
|
|
|
|
+ return a
|
|
|
|
|
+ }
|
|
|
|
|
+ return b
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func maxDuration(a, b time.Duration) time.Duration {
|
|
|
|
|
+ if a > b {
|
|
|
|
|
+ return a
|
|
|
|
|
+ }
|
|
|
|
|
+ return b
|
|
|
|
|
+}
|