Skip to content

Commit a8e7ae4

Browse files
committed
lower cyclomatic complexity
1 parent e4d075d commit a8e7ae4

File tree

4 files changed

+235
-190
lines changed

4 files changed

+235
-190
lines changed

wasp/benchspy/direct.go

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -174,62 +174,53 @@ func (g *DirectQueryExecutor) generateStandardQueries() (map[string]DirectQueryF
174174
}
175175

176176
func (g *DirectQueryExecutor) standardQuery(standardMetric StandardLoadMetric) (DirectQueryFn, error) {
177+
var responsesToDurationFn = func(responses *wasp.SliceBuffer[*wasp.Response]) []float64 {
178+
var asMiliDuration []float64
179+
for _, response := range responses.Data {
180+
// get duration as nanoseconds and convert to milliseconds in order to not lose precision
181+
// otherwise, the duration will be rounded to the nearest millisecond
182+
asMiliDuration = append(asMiliDuration, float64(response.Duration.Nanoseconds())/1_000_000)
183+
}
184+
185+
return asMiliDuration
186+
}
187+
188+
var calculateFailureRateFn = func(responses *wasp.SliceBuffer[*wasp.Response]) (float64, error) {
189+
if len(responses.Data) == 0 {
190+
return 0, nil
191+
}
192+
193+
failedCount := 0.0
194+
successfulCount := 0.0
195+
for _, response := range responses.Data {
196+
if response.Failed || response.Timeout {
197+
failedCount = failedCount + 1
198+
} else {
199+
successfulCount = successfulCount + 1
200+
}
201+
}
202+
203+
return failedCount / (failedCount + successfulCount), nil
204+
}
205+
177206
switch standardMetric {
178207
case MedianLatency:
179208
medianFn := func(responses *wasp.SliceBuffer[*wasp.Response]) (float64, error) {
180-
var asMiliDuration []float64
181-
for _, response := range responses.Data {
182-
// get duration as nanoseconds and convert to milliseconds in order to not lose precision
183-
// otherwise, the duration will be rounded to the nearest millisecond
184-
asMiliDuration = append(asMiliDuration, float64(response.Duration.Nanoseconds())/1_000_000)
185-
}
186-
187-
return stats.Median(asMiliDuration)
209+
return stats.Median(responsesToDurationFn(responses))
188210
}
189211
return medianFn, nil
190212
case Percentile95Latency:
191213
p95Fn := func(responses *wasp.SliceBuffer[*wasp.Response]) (float64, error) {
192-
var asMiliDuration []float64
193-
for _, response := range responses.Data {
194-
// get duration as nanoseconds and convert to milliseconds in order to not lose precision
195-
// otherwise, the duration will be rounded to the nearest millisecond
196-
asMiliDuration = append(asMiliDuration, float64(response.Duration.Nanoseconds())/1_000_000)
197-
}
198-
199-
return stats.Percentile(asMiliDuration, 95)
214+
return stats.Percentile(responsesToDurationFn(responses), 95)
200215
}
201216
return p95Fn, nil
202217
case MaxLatency:
203218
maxFn := func(responses *wasp.SliceBuffer[*wasp.Response]) (float64, error) {
204-
var asMiliDuration []float64
205-
for _, response := range responses.Data {
206-
// get duration as nanoseconds and convert to milliseconds in order to not lose precision
207-
// otherwise, the duration will be rounded to the nearest millisecond
208-
asMiliDuration = append(asMiliDuration, float64(response.Duration.Nanoseconds())/1_000_000)
209-
}
210-
211-
return stats.Max(asMiliDuration)
219+
return stats.Max(responsesToDurationFn(responses))
212220
}
213221
return maxFn, nil
214222
case ErrorRate:
215-
errorRateFn := func(responses *wasp.SliceBuffer[*wasp.Response]) (float64, error) {
216-
if len(responses.Data) == 0 {
217-
return 0, nil
218-
}
219-
220-
failedCount := 0.0
221-
successfulCount := 0.0
222-
for _, response := range responses.Data {
223-
if response.Failed || response.Timeout {
224-
failedCount = failedCount + 1
225-
} else {
226-
successfulCount = successfulCount + 1
227-
}
228-
}
229-
230-
return failedCount / (failedCount + successfulCount), nil
231-
}
232-
return errorRateFn, nil
223+
return calculateFailureRateFn, nil
233224
default:
234225
return nil, fmt.Errorf("unsupported standard metric %s", standardMetric)
235226
}

wasp/benchspy/report.go

Lines changed: 104 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -422,31 +422,36 @@ func NewStandardReport(commitOrTag string, opts ...StandardReportOption) (*Stand
422422
return nil, basicValidateErr
423423
}
424424

425-
var queryExecutors []QueryExecutor
426-
if len(config.executorTypes) != 0 {
427-
for _, g := range config.generators {
428-
for _, exType := range config.executorTypes {
429-
if exType != StandardQueryExecutor_Prometheus {
430-
executor, executorErr := initStandardQueryExecutor(exType, basicData, g)
431-
if executorErr != nil {
432-
return nil, errors.Wrapf(executorErr, "failed to create standard %s query executor for generator %s", exType, g.Cfg.GenName)
433-
}
434-
435-
validateErr := executor.Validate()
436-
if validateErr != nil {
437-
return nil, errors.Wrapf(validateErr, "failed to validate queries for generator %s", g.Cfg.GenName)
438-
}
439-
440-
queryExecutors = append(queryExecutors, executor)
441-
}
442-
}
443-
}
425+
queryExecutors, initErr := initStandardLoadExecutors(config, basicData)
426+
if initErr != nil {
427+
return nil, errors.Wrap(initErr, "failed to initialize standard query executors")
444428
}
445429

446430
if len(config.queryExecutors) > 0 {
447431
queryExecutors = append(queryExecutors, config.queryExecutors...)
448432
}
449433

434+
prometheusExecutors, promErr := initPrometheusQueryExecutor(config, basicData)
435+
if promErr != nil {
436+
return nil, errors.Wrap(promErr, "failed to initialize prometheus query executor")
437+
}
438+
439+
queryExecutors = append(queryExecutors, prometheusExecutors...)
440+
441+
sr := &StandardReport{
442+
BasicData: *basicData,
443+
QueryExecutors: queryExecutors,
444+
}
445+
446+
if config.reportDirectory != "" {
447+
sr.LocalStorage.Directory = config.reportDirectory
448+
}
449+
450+
return sr, nil
451+
}
452+
453+
func initPrometheusQueryExecutor(config standardReportConfig, basicData *BasicData) ([]QueryExecutor, error) {
454+
var queryExecutors []QueryExecutor
450455
if config.prometheusConfig != WithoutPrometheus {
451456
// not ideal, but we want to follow the same pattern as with other executors
452457
for _, n := range config.prometheusConfig.NameRegexPatterns {
@@ -462,16 +467,32 @@ func NewStandardReport(commitOrTag string, opts ...StandardReportOption) (*Stand
462467
}
463468
}
464469

465-
sr := &StandardReport{
466-
BasicData: *basicData,
467-
QueryExecutors: queryExecutors,
468-
}
470+
return queryExecutors, nil
471+
}
469472

470-
if config.reportDirectory != "" {
471-
sr.LocalStorage.Directory = config.reportDirectory
473+
func initStandardLoadExecutors(config standardReportConfig, basicData *BasicData) ([]QueryExecutor, error) {
474+
var queryExecutors []QueryExecutor
475+
if len(config.executorTypes) != 0 {
476+
for _, g := range config.generators {
477+
for _, exType := range config.executorTypes {
478+
if exType != StandardQueryExecutor_Prometheus {
479+
executor, executorErr := initStandardQueryExecutor(exType, basicData, g)
480+
if executorErr != nil {
481+
return nil, errors.Wrapf(executorErr, "failed to create standard %s query executor for generator %s", exType, g.Cfg.GenName)
482+
}
483+
484+
validateErr := executor.Validate()
485+
if validateErr != nil {
486+
return nil, errors.Wrapf(validateErr, "failed to validate queries for generator %s", g.Cfg.GenName)
487+
}
488+
489+
queryExecutors = append(queryExecutors, executor)
490+
}
491+
}
492+
}
472493
}
473494

474-
return sr, nil
495+
return queryExecutors, nil
475496
}
476497

477498
func initStandardQueryExecutor(kind StandardQueryExecutorType, basicData *BasicData, g *wasp.Generator) (QueryExecutor, error) {
@@ -568,6 +589,60 @@ func unmarshallQueryExecutors(raw []json.RawMessage) ([]QueryExecutor, error) {
568589
func convertQueryResults(results map[string]interface{}) (map[string]interface{}, error) {
569590
converted := make(map[string]interface{})
570591

592+
var convertToStringSlice = func(v []interface{}, key string) {
593+
strSlice := make([]string, len(v))
594+
allConverted := true
595+
for i, elem := range v {
596+
str, ok := elem.(string)
597+
if !ok {
598+
// return original slice if we can't convert, because its composed of different types
599+
converted[key] = v
600+
allConverted = false
601+
break
602+
}
603+
strSlice[i] = str
604+
}
605+
if allConverted {
606+
converted[key] = strSlice
607+
}
608+
}
609+
610+
var convertToIntSlice = func(v []interface{}, key string) {
611+
intSlice := make([]int, len(v))
612+
allConverted := true
613+
for i, elem := range v {
614+
num, ok := elem.(int)
615+
if !ok {
616+
// return original slice if we can't convert, because its composed of different types
617+
converted[key] = v
618+
allConverted = false
619+
break
620+
}
621+
intSlice[i] = num
622+
}
623+
if allConverted {
624+
converted[key] = intSlice
625+
}
626+
}
627+
628+
var convertToFloatSlice = func(v []interface{}, key string) {
629+
floatSlice := make([]float64, len(v))
630+
allConverted := true
631+
for i, elem := range v {
632+
f, ok := elem.(float64)
633+
if !ok {
634+
// return original slice if we can't convert, because its composed of different types
635+
converted[key] = v
636+
allConverted = false
637+
break
638+
}
639+
floatSlice[i] = f
640+
}
641+
if allConverted {
642+
converted[key] = floatSlice
643+
}
644+
}
645+
571646
for key, value := range results {
572647
switch v := value.(type) {
573648
case string, int, float64:
@@ -580,53 +655,11 @@ func convertQueryResults(results map[string]interface{}) (map[string]interface{}
580655
// Convert first element to determine slice type
581656
switch v[0].(type) {
582657
case string:
583-
strSlice := make([]string, len(v))
584-
allConverted := true
585-
for i, elem := range v {
586-
str, ok := elem.(string)
587-
if !ok {
588-
// return original slice if we can't convert, because its composed of different types
589-
converted[key] = v
590-
allConverted = false
591-
break
592-
}
593-
strSlice[i] = str
594-
}
595-
if allConverted {
596-
converted[key] = strSlice
597-
}
658+
convertToStringSlice(v, key)
598659
case int:
599-
intSlice := make([]int, len(v))
600-
allConverted := true
601-
for i, elem := range v {
602-
num, ok := elem.(int)
603-
if !ok {
604-
// return original slice if we can't convert, because its composed of different types
605-
converted[key] = v
606-
allConverted = false
607-
break
608-
}
609-
intSlice[i] = num
610-
}
611-
if allConverted {
612-
converted[key] = intSlice
613-
}
660+
convertToIntSlice(v, key)
614661
case float64:
615-
floatSlice := make([]float64, len(v))
616-
allConverted := true
617-
for i, elem := range v {
618-
f, ok := elem.(float64)
619-
if !ok {
620-
// return original slice if we can't convert, because its composed of different types
621-
converted[key] = v
622-
allConverted = false
623-
break
624-
}
625-
floatSlice[i] = f
626-
}
627-
if allConverted {
628-
converted[key] = floatSlice
629-
}
662+
convertToFloatSlice(v, key)
630663
default:
631664
// do nothing if it's not a type we can convert
632665
converted[key] = v

wasp/benchspy/report_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func TestBenchSpy_NewStandardReportWithPrometheus(t *testing.T) {
162162
WithPrometheusConfig(multiPromConfig))
163163
require.NoError(t, err)
164164
assert.NotNil(t, report)
165-
assert.Equal(t, 2, len(report.QueryExecutors))
165+
require.Equal(t, 2, len(report.QueryExecutors))
166166
assert.IsType(t, &PrometheusQueryExecutor{}, report.QueryExecutors[0])
167167
assert.IsType(t, &PrometheusQueryExecutor{}, report.QueryExecutors[1])
168168
firstAsProm := report.QueryExecutors[0].(*PrometheusQueryExecutor)

0 commit comments

Comments
 (0)