mirror of
https://github.com/akvorado/akvorado.git
synced 2025-12-12 06:24:10 +01:00
console: add 95th percentile
This commit is contained in:
@@ -86,6 +86,7 @@ const table = computed(() => {
|
||||
{ name: "Min", classNames: "text-right" },
|
||||
{ name: "Max", classNames: "text-right" },
|
||||
{ name: "Average", classNames: "text-right" },
|
||||
{ name: "~95th", classNames: "text-right" },
|
||||
],
|
||||
rows:
|
||||
data.rows?.map((rows, idx) => {
|
||||
@@ -97,7 +98,12 @@ const table = computed(() => {
|
||||
// Dimensions
|
||||
...rows.map((r) => ({ value: r })),
|
||||
// Stats
|
||||
...[data.min[idx], data.max[idx], data.average[idx]].map((d) => ({
|
||||
...[
|
||||
data.min[idx],
|
||||
data.max[idx],
|
||||
data.average[idx],
|
||||
data["95th"][idx],
|
||||
].map((d) => ({
|
||||
value: formatBps(d) + "bps",
|
||||
classNames: "text-right tabular-nums",
|
||||
})),
|
||||
|
||||
@@ -81,12 +81,13 @@ ORDER BY time`, strings.Join(with, ",\n "), strings.Join(fields, ",\n "), where)
|
||||
}
|
||||
|
||||
type graphHandlerOutput struct {
|
||||
Rows [][]string `json:"rows"`
|
||||
Time []time.Time `json:"t"`
|
||||
Points [][]int `json:"points"` // t → row → bps
|
||||
Average []int `json:"average"` // row → bps
|
||||
Min []int `json:"min"`
|
||||
Max []int `json:"max"`
|
||||
Rows [][]string `json:"rows"`
|
||||
Time []time.Time `json:"t"`
|
||||
Points [][]int `json:"points"` // t → row → bps
|
||||
Average []int `json:"average"` // row → bps
|
||||
Min []int `json:"min"`
|
||||
Max []int `json:"max"`
|
||||
NinetyFivePercentile []int `json:"95th"`
|
||||
}
|
||||
|
||||
func (c *Component) graphHandlerFunc(gc *gin.Context) {
|
||||
@@ -174,18 +175,38 @@ func (c *Component) graphHandlerFunc(gc *gin.Context) {
|
||||
output.Average = make([]int, len(rows))
|
||||
output.Min = make([]int, len(rows))
|
||||
output.Max = make([]int, len(rows))
|
||||
output.NinetyFivePercentile = make([]int, len(rows))
|
||||
|
||||
for idx, r := range rows {
|
||||
output.Rows[idx] = rowKeys[r]
|
||||
output.Points[idx] = rowValues[r]
|
||||
output.Average[idx] = int(rowSums[r] / uint64(len(output.Time)))
|
||||
for j, v := range rowValues[r] {
|
||||
if j == 0 || output.Min[idx] > v {
|
||||
output.Min[idx] = v
|
||||
}
|
||||
if j == 0 || output.Max[idx] < v {
|
||||
output.Max[idx] = v
|
||||
}
|
||||
// For 95th percentile, we need to sort the values.
|
||||
// Use that for min/max too.
|
||||
if len(rowValues[r]) == 0 {
|
||||
continue
|
||||
}
|
||||
if len(rowValues[r]) == 1 {
|
||||
v := rowValues[r][0]
|
||||
output.Min[idx] = v
|
||||
output.Max[idx] = v
|
||||
output.NinetyFivePercentile[idx] = v
|
||||
continue
|
||||
}
|
||||
|
||||
s := make([]int, len(rowValues[r]))
|
||||
copy(s, rowValues[r])
|
||||
sort.Ints(s)
|
||||
output.Min[idx] = s[0]
|
||||
output.Max[idx] = s[len(s)-1]
|
||||
index := 0.95 * float64(len(s))
|
||||
j := int(index)
|
||||
if index == float64(j) {
|
||||
output.NinetyFivePercentile[idx] = s[j-1]
|
||||
} else if index > 1 {
|
||||
// We use the average of the two values. This
|
||||
// is good enough for bps
|
||||
output.NinetyFivePercentile[idx] = (s[j-1] + s[j]) / 2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +183,14 @@ func TestGraphHandler(t *testing.T) {
|
||||
333,
|
||||
700,
|
||||
},
|
||||
"95th": []int{
|
||||
4000,
|
||||
750,
|
||||
600,
|
||||
550,
|
||||
500,
|
||||
1000,
|
||||
},
|
||||
}
|
||||
mockConn.EXPECT().
|
||||
Select(gomock.Any(), gomock.Any(), gomock.Any()).
|
||||
|
||||
Reference in New Issue
Block a user