diff --git a/quesma/quesma/ui/ab_testing.go b/quesma/quesma/ui/ab_testing.go index 893842eb1..5f2c2a511 100644 --- a/quesma/quesma/ui/ab_testing.go +++ b/quesma/quesma/ui/ab_testing.go @@ -10,6 +10,7 @@ import ( "quesma/elasticsearch" "quesma/jsondiff" "quesma/logger" + "quesma/quesma/config" "quesma/quesma/ui/internal/builder" "strings" "time" @@ -75,7 +76,6 @@ If the performance gain is positive, it means that the second backend connector buffer.Html(``) buffer.Html(`
`) @@ -86,7 +86,7 @@ If the performance gain is positive, it means that the second backend connector buffer.Html(`") } else { - buffer.Html(`

A/B Testing results are not available.

`) + buffer.Html(`

CR results are not available.

`) } buffer.Html("\n\n\n") @@ -258,17 +258,19 @@ func formatJSON(in *string) string { } type abTestingReportRow struct { - dashboardId string - panelId string - dashboardUrl string - detailsUrl string - dashboardName string - panelName string - aName string - bName string - successRate *float64 - performanceGain *float64 - count int + dashboardId string + panelId string + dashboardUrl string + detailsUrl string + dashboardName string + panelName string + aName string + bName string + aTime *float64 + bTime *float64 + successRate *float64 + responseTimeDelta *float64 + count int } func (qmc *QuesmaManagementConsole) abTestingReadReport(kibanaUrl, orderBy string) ([]abTestingReportRow, error) { @@ -281,7 +283,6 @@ func (qmc *QuesmaManagementConsole) abTestingReadReport(kibanaUrl, orderBy strin orderByToSQL := map[string]string{ "default": "dashboard_id, panel_id, a_name, b_name", "response_similarity": "response_similarity DESC, dashboard_id, panel_id, a_name, b_name", - "performance_gain": "performance_gain DESC,dashboard_id, panel_id, a_name, b_name", "count": "count DESC,dashboard_id, panel_id, a_name, b_name", } @@ -311,8 +312,10 @@ SELECT a_name, b_name, (sumIf(c,ok)/ sum(c)) * 100 as response_similarity, - ((avgIf(a_time,ok)- avgIf(b_time,ok))/avgIf(a_time,ok))*100.0 as performance_gain, - sum(c) as count + + sum(c) as count, + avgIf(a_time,ok) as a_time, + avgIf(b_time,ok) as b_time FROM subresults GROUP BY @@ -331,7 +334,7 @@ GROUP BY for rows.Next() { row := abTestingReportRow{} - err := rows.Scan(&row.dashboardId, &row.panelId, &row.aName, &row.bName, &row.successRate, &row.performanceGain, &row.count) + err := rows.Scan(&row.dashboardId, &row.panelId, &row.aName, &row.bName, &row.successRate, &row.count, &row.aTime, &row.bTime) if err != nil { return nil, err } @@ -341,6 +344,26 @@ GROUP BY row.dashboardName = kibanaDashboards.dashboardName(row.dashboardId) row.panelName = kibanaDashboards.panelName(row.dashboardId, row.panelId) + if row.aTime != nil && row.bTime != nil { + + var clickhouseTime, elasticTime float64 + + if row.aName == config.ElasticsearchTarget { + elasticTime = *row.aTime + clickhouseTime = *row.bTime + } else { + elasticTime = *row.bTime + clickhouseTime = *row.aTime + } + + if elasticTime == 0 { + row.responseTimeDelta = nil + } else { + delta := (elasticTime - clickhouseTime) / elasticTime * 100 + row.responseTimeDelta = &delta + } + } + result = append(result, row) } @@ -361,7 +384,7 @@ func (qmc *QuesmaManagementConsole) generateABTestingReport(kibanaUrl, orderBy s buffer.Html(`Panel` + "\n") buffer.Html(`Count
(since start)` + "\n") buffer.Html(`Response similarity` + "\n") - buffer.Html(`Performance gain` + "\n") + buffer.Html(`Response time delta` + "\n") buffer.Html(`` + "\n") buffer.Html("\n") buffer.Html("\n") @@ -405,8 +428,36 @@ func (qmc *QuesmaManagementConsole) generateABTestingReport(kibanaUrl, orderBy s buffer.Html(``) buffer.Html(``) - if row.performanceGain != nil { - buffer.Text(fmt.Sprintf("%.01f%%", *row.performanceGain)) + + const minTime = 0.05 // 50ms, we don't show performance gain for queries faster than this + const maxTime = 5.0 // if a query takes longer than this, we show the name of the slowest backend + + if row.responseTimeDelta != nil { + buffer.Html(``) + + switch { + + case *row.aTime < minTime && *row.bTime < minTime: + buffer.Text("both < 50ms") + + case *row.aTime > maxTime && *row.bTime < maxTime: + buffer.Text(fmt.Sprintf("%s is over %0.02fs", row.aName, *row.aTime)) + + case *row.bTime > maxTime && *row.aTime < maxTime: + buffer.Text(fmt.Sprintf("%s is over %0.02fs", row.bName, *row.bTime)) + + default: + + if *row.responseTimeDelta > 0 { + buffer.Text(fmt.Sprintf("%.01f%% faster", *row.responseTimeDelta)) + } else { + buffer.Text(fmt.Sprintf("%.01f%% slower", -(*row.responseTimeDelta))) + } + + } + buffer.Html(``) } else { buffer.Text("n/a") } @@ -536,7 +587,7 @@ func (qmc *QuesmaManagementConsole) generateABPanelDetails(dashboardId, panelId buffer.Html(`
`) - buffer.Html(`

A/B Testing - Panel Details

`) + buffer.Html(`

Compatibility report - Panel Details

`) buffer.Html(`

`) buffer.Text(fmt.Sprintf("Dashboard: %s", dashboardName)) buffer.Html(`

`) @@ -671,7 +722,7 @@ func (qmc *QuesmaManagementConsole) generateABMismatchDetails(dashboardId, panel buffer.Html(`
`) - buffer.Html(`

A/B Testing - Panel requests

`) + buffer.Html(`

Compatibility report - Panel requests

`) buffer.Html(`

`) buffer.Text(fmt.Sprintf("Dashboard: %s", dashboardName)) @@ -796,7 +847,7 @@ func (qmc *QuesmaManagementConsole) generateABSingleRequest(requestId string) [] buffer := newBufferWithHead() buffer.Html(`
`) - buffer.Html(`

A/B Testing - Request Results

`) + buffer.Html(`

Compatibility report - Request Results

`) fmtAny := func(value any) string { if value == nil { diff --git a/quesma/quesma/ui/html_utils.go b/quesma/quesma/ui/html_utils.go index 28dab3790..a4db956f9 100644 --- a/quesma/quesma/ui/html_utils.go +++ b/quesma/quesma/ui/html_utils.go @@ -81,9 +81,9 @@ func (qmc *QuesmaManagementConsole) generateTopNavigation(target string) []byte if target == "ab-testing-dashboard" { buffer.Html(` class="active"`) } - buffer.Html(`>A/B`) + buffer.Html(`">CR`) if qmc.isAuthEnabled { buffer.Html(`
  • Logout
  • `)