Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit 87656c9

Browse files
A/B - Performance gain change (#967)
This PR adds a different rendering of performance gain for extreme values: 1. when both response times are speedy (<50ms) we don't compute a gain, it doesn't make sense 2. when one of the sides is significantly slower (over 5s), we show which is slower (it may be an infrastructure issue) <img width="597" alt="Screenshot 2024-11-11 at 14 51 48" src="https://github.com/user-attachments/assets/9a545ecd-893b-4e68-a85f-61257a97766c"> --------- Signed-off-by: Rafał Strzaliński <[email protected]> Co-authored-by: Piotr Grabowski <[email protected]>
1 parent 58d0cc1 commit 87656c9

File tree

2 files changed

+76
-25
lines changed

2 files changed

+76
-25
lines changed

quesma/quesma/ui/ab_testing.go

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"quesma/elasticsearch"
1111
"quesma/jsondiff"
1212
"quesma/logger"
13+
"quesma/quesma/config"
1314
"quesma/quesma/ui/internal/builder"
1415
"strings"
1516
"time"
@@ -75,7 +76,6 @@ If the performance gain is positive, it means that the second backend connector
7576
buffer.Html(`<select id="order_by" name="order_by">`)
7677
buffer.Html(`<option value="default">Default</option>`)
7778
buffer.Html(`<option value="response_similarity">Response similarity</option>`)
78-
buffer.Html(`<option value="performance_gain">Performance gain</option>`)
7979
buffer.Html(`<option value="count">Count</option>`)
8080
buffer.Html(`</select>`)
8181
buffer.Html(`<br>`)
@@ -86,7 +86,7 @@ If the performance gain is positive, it means that the second backend connector
8686
buffer.Html(`<div class="menu">`)
8787
buffer.Html("\n</div>")
8888
} else {
89-
buffer.Html(`<p>A/B Testing results are not available.</p>`)
89+
buffer.Html(`<p>CR results are not available.</p>`)
9090
}
9191

9292
buffer.Html("\n</main>\n\n")
@@ -258,17 +258,19 @@ func formatJSON(in *string) string {
258258
}
259259

260260
type abTestingReportRow struct {
261-
dashboardId string
262-
panelId string
263-
dashboardUrl string
264-
detailsUrl string
265-
dashboardName string
266-
panelName string
267-
aName string
268-
bName string
269-
successRate *float64
270-
performanceGain *float64
271-
count int
261+
dashboardId string
262+
panelId string
263+
dashboardUrl string
264+
detailsUrl string
265+
dashboardName string
266+
panelName string
267+
aName string
268+
bName string
269+
aTime *float64
270+
bTime *float64
271+
successRate *float64
272+
responseTimeDelta *float64
273+
count int
272274
}
273275

274276
func (qmc *QuesmaManagementConsole) abTestingReadReport(kibanaUrl, orderBy string) ([]abTestingReportRow, error) {
@@ -281,7 +283,6 @@ func (qmc *QuesmaManagementConsole) abTestingReadReport(kibanaUrl, orderBy strin
281283
orderByToSQL := map[string]string{
282284
"default": "dashboard_id, panel_id, a_name, b_name",
283285
"response_similarity": "response_similarity DESC, dashboard_id, panel_id, a_name, b_name",
284-
"performance_gain": "performance_gain DESC,dashboard_id, panel_id, a_name, b_name",
285286
"count": "count DESC,dashboard_id, panel_id, a_name, b_name",
286287
}
287288

@@ -311,8 +312,10 @@ SELECT
311312
a_name,
312313
b_name,
313314
(sumIf(c,ok)/ sum(c)) * 100 as response_similarity,
314-
((avgIf(a_time,ok)- avgIf(b_time,ok))/avgIf(a_time,ok))*100.0 as performance_gain,
315-
sum(c) as count
315+
316+
sum(c) as count,
317+
avgIf(a_time,ok) as a_time,
318+
avgIf(b_time,ok) as b_time
316319
FROM
317320
subresults
318321
GROUP BY
@@ -331,7 +334,7 @@ GROUP BY
331334

332335
for rows.Next() {
333336
row := abTestingReportRow{}
334-
err := rows.Scan(&row.dashboardId, &row.panelId, &row.aName, &row.bName, &row.successRate, &row.performanceGain, &row.count)
337+
err := rows.Scan(&row.dashboardId, &row.panelId, &row.aName, &row.bName, &row.successRate, &row.count, &row.aTime, &row.bTime)
335338
if err != nil {
336339
return nil, err
337340
}
@@ -341,6 +344,26 @@ GROUP BY
341344
row.dashboardName = kibanaDashboards.dashboardName(row.dashboardId)
342345
row.panelName = kibanaDashboards.panelName(row.dashboardId, row.panelId)
343346

347+
if row.aTime != nil && row.bTime != nil {
348+
349+
var clickhouseTime, elasticTime float64
350+
351+
if row.aName == config.ElasticsearchTarget {
352+
elasticTime = *row.aTime
353+
clickhouseTime = *row.bTime
354+
} else {
355+
elasticTime = *row.bTime
356+
clickhouseTime = *row.aTime
357+
}
358+
359+
if elasticTime == 0 {
360+
row.responseTimeDelta = nil
361+
} else {
362+
delta := (elasticTime - clickhouseTime) / elasticTime * 100
363+
row.responseTimeDelta = &delta
364+
}
365+
}
366+
344367
result = append(result, row)
345368
}
346369

@@ -361,7 +384,7 @@ func (qmc *QuesmaManagementConsole) generateABTestingReport(kibanaUrl, orderBy s
361384
buffer.Html(`<th class="key">Panel</th>` + "\n")
362385
buffer.Html(`<th class="key">Count <br> <small>(since start)</small></th>` + "\n")
363386
buffer.Html(`<th class="key">Response similarity</th>` + "\n")
364-
buffer.Html(`<th class="key">Performance gain</th>` + "\n")
387+
buffer.Html(`<th class="key">Response time delta</th>` + "\n")
365388
buffer.Html(`<th class="key"></th>` + "\n")
366389
buffer.Html("</tr>\n")
367390
buffer.Html("</thead>\n")
@@ -405,8 +428,36 @@ func (qmc *QuesmaManagementConsole) generateABTestingReport(kibanaUrl, orderBy s
405428
buffer.Html(`</td>`)
406429

407430
buffer.Html(`<td>`)
408-
if row.performanceGain != nil {
409-
buffer.Text(fmt.Sprintf("%.01f%%", *row.performanceGain))
431+
432+
const minTime = 0.05 // 50ms, we don't show performance gain for queries faster than this
433+
const maxTime = 5.0 // if a query takes longer than this, we show the name of the slowest backend
434+
435+
if row.responseTimeDelta != nil {
436+
buffer.Html(`<span title="`)
437+
buffer.Html(fmt.Sprintf("%s=%.03fs, %s=%.03fs", row.aName, *row.aTime, row.bName, *row.bTime))
438+
buffer.Html(`">`)
439+
440+
switch {
441+
442+
case *row.aTime < minTime && *row.bTime < minTime:
443+
buffer.Text("both < 50ms")
444+
445+
case *row.aTime > maxTime && *row.bTime < maxTime:
446+
buffer.Text(fmt.Sprintf("%s is over %0.02fs", row.aName, *row.aTime))
447+
448+
case *row.bTime > maxTime && *row.aTime < maxTime:
449+
buffer.Text(fmt.Sprintf("%s is over %0.02fs", row.bName, *row.bTime))
450+
451+
default:
452+
453+
if *row.responseTimeDelta > 0 {
454+
buffer.Text(fmt.Sprintf("%.01f%% faster", *row.responseTimeDelta))
455+
} else {
456+
buffer.Text(fmt.Sprintf("%.01f%% slower", -(*row.responseTimeDelta)))
457+
}
458+
459+
}
460+
buffer.Html(`</span>`)
410461
} else {
411462
buffer.Text("n/a")
412463
}
@@ -536,7 +587,7 @@ func (qmc *QuesmaManagementConsole) generateABPanelDetails(dashboardId, panelId
536587

537588
buffer.Html(`<main id="ab_testing_dashboard">`)
538589

539-
buffer.Html(`<h2>A/B Testing - Panel Details</h2>`)
590+
buffer.Html(`<h2>Compatibility report - Panel Details</h2>`)
540591
buffer.Html(`<h3>`)
541592
buffer.Text(fmt.Sprintf("Dashboard: %s", dashboardName))
542593
buffer.Html(`</h3>`)
@@ -671,7 +722,7 @@ func (qmc *QuesmaManagementConsole) generateABMismatchDetails(dashboardId, panel
671722

672723
buffer.Html(`<main id="ab_testing_dashboard">`)
673724

674-
buffer.Html(`<h2>A/B Testing - Panel requests</h2>`)
725+
buffer.Html(`<h2>Compatibility report - Panel requests</h2>`)
675726

676727
buffer.Html(`<h3>`)
677728
buffer.Text(fmt.Sprintf("Dashboard: %s", dashboardName))
@@ -796,7 +847,7 @@ func (qmc *QuesmaManagementConsole) generateABSingleRequest(requestId string) []
796847
buffer := newBufferWithHead()
797848
buffer.Html(`<main id="ab_testing_dashboard">`)
798849

799-
buffer.Html(`<h2>A/B Testing - Request Results </h2>`)
850+
buffer.Html(`<h2>Compatibility report - Request Results </h2>`)
800851

801852
fmtAny := func(value any) string {
802853
if value == nil {

quesma/quesma/ui/html_utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ func (qmc *QuesmaManagementConsole) generateTopNavigation(target string) []byte
8181
if target == "ab-testing-dashboard" {
8282
buffer.Html(` class="active"`)
8383
}
84-
buffer.Html(`><a href="`)
84+
buffer.Html(`><a title="Compatibility Report" href="`)
8585
buffer.Html(abTestingPath)
86-
buffer.Html(`">A/B</a></li>`)
86+
buffer.Html(`">CR</a></li>`)
8787

8888
if qmc.isAuthEnabled {
8989
buffer.Html(`<li><a href="/logout">Logout</a></li>`)

0 commit comments

Comments
 (0)