Skip to content

Commit 19067db

Browse files
committed
fix(cli): log dropped recs from --min-pool-size filter (closes #359)
applyFilters now emits one INFO line per dropped rec: INFO: --min-pool-size=2.0 dropped rds/us-east-1/db.t3.micro (avg=0.80 < threshold) and a summary line after all drops are counted: INFO: --min-pool-size dropped N recommendation(s) (X avg instances/hr total) The pool-size check is lifted out of passesDimensionFilters and evaluated first in applyFilters so drops can be observed and counted without adding side effects to the pure shouldIncludePoolSize predicate. Adds TestShouldIncludePoolSize (5 cases) and TestApplyFilters_PoolSizeLogs to assert both the per-rec and summary log lines.
1 parent 4956d66 commit 19067db

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

cmd/multi_service_filters.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package main
22

33
import (
4+
"fmt"
5+
"log"
46
"slices"
57
"strings"
68

@@ -11,14 +13,27 @@ import (
1113
// currentRegion is the region being processed in the current loop iteration - if non-empty, only recommendations for that region are included
1214
func applyFilters(recs []common.Recommendation, cfg Config, instanceVersions map[string][]InstanceEngineVersion, versionInfo map[string]MajorEngineVersionInfo, currentRegion string) []common.Recommendation {
1315
var filtered []common.Recommendation
16+
var poolDrops []string
17+
var poolDropInstances float64
1418

1519
for _, rec := range recs {
20+
if cfg.MinPoolSize > 0 && !shouldIncludePoolSize(rec, cfg) {
21+
poolDropInstances += rec.AverageInstancesUsedPerHour
22+
label := fmt.Sprintf("%s/%s/%s", rec.Service, rec.Region, rec.ResourceType)
23+
log.Printf("INFO: --min-pool-size=%.1f dropped %s (avg=%.2f < threshold)", cfg.MinPoolSize, label, rec.AverageInstancesUsedPerHour)
24+
poolDrops = append(poolDrops, label)
25+
continue
26+
}
1627
adjusted, include := processRecommendation(rec, cfg, instanceVersions, versionInfo, currentRegion)
1728
if include {
1829
filtered = append(filtered, adjusted)
1930
}
2031
}
2132

33+
if len(poolDrops) > 0 {
34+
log.Printf("INFO: --min-pool-size dropped %d recommendation(s) (%.2f avg instances/hr total)", len(poolDrops), poolDropInstances)
35+
}
36+
2237
return filtered
2338
}
2439

cmd/multi_service_filters_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package main
22

33
import (
4+
"bytes"
5+
"log"
46
"testing"
57

68
"github.com/LeanerCloud/CUDly/pkg/common"
@@ -413,3 +415,62 @@ func TestShouldIncludeAccount(t *testing.T) {
413415
})
414416
}
415417
}
418+
419+
func TestShouldIncludePoolSize(t *testing.T) {
420+
tests := []struct {
421+
name string
422+
avg float64
423+
minPool float64
424+
expected bool
425+
}{
426+
{"filter disabled (0)", 0.5, 0, true},
427+
{"avg=0 passes through", 0, 2.0, true},
428+
{"avg below threshold", 1.5, 2.0, false},
429+
{"avg equal to threshold", 2.0, 2.0, true},
430+
{"avg above threshold", 3.0, 2.0, true},
431+
}
432+
433+
for _, tt := range tests {
434+
t.Run(tt.name, func(t *testing.T) {
435+
rec := common.Recommendation{AverageInstancesUsedPerHour: tt.avg}
436+
cfg := Config{MinPoolSize: tt.minPool}
437+
assert.Equal(t, tt.expected, shouldIncludePoolSize(rec, cfg))
438+
})
439+
}
440+
}
441+
442+
// TestApplyFilters_PoolSizeLogs verifies that applyFilters emits per-rec and
443+
// summary log lines when --min-pool-size drops recommendations.
444+
func TestApplyFilters_PoolSizeLogs(t *testing.T) {
445+
origCfg := toolCfg
446+
defer func() { toolCfg = origCfg }()
447+
448+
// Capture log output.
449+
var buf bytes.Buffer
450+
origFlags := log.Flags()
451+
origWriter := log.Writer()
452+
log.SetOutput(&buf)
453+
log.SetFlags(0) // strip timestamps so the assertions are stable
454+
defer func() {
455+
log.SetOutput(origWriter)
456+
log.SetFlags(origFlags)
457+
}()
458+
459+
recs := []common.Recommendation{
460+
{Service: "rds", Region: "us-east-1", ResourceType: "db.t3.micro", AverageInstancesUsedPerHour: 0.8, Count: 1},
461+
{Service: "rds", Region: "us-east-1", ResourceType: "db.r5.large", AverageInstancesUsedPerHour: 3.5, Count: 2},
462+
}
463+
cfg := Config{MinPoolSize: 2.0}
464+
465+
result := applyFilters(recs, cfg, nil, nil, "")
466+
467+
// Only the rec above threshold passes through.
468+
assert.Len(t, result, 1)
469+
assert.Equal(t, "db.r5.large", result[0].ResourceType)
470+
471+
output := buf.String()
472+
// Per-rec line present.
473+
assert.Contains(t, output, "--min-pool-size=2.0 dropped rds/us-east-1/db.t3.micro (avg=0.80 < threshold)")
474+
// Summary line present.
475+
assert.Contains(t, output, "--min-pool-size dropped 1 recommendation(s)")
476+
}

0 commit comments

Comments
 (0)