Skip to content

Commit e41b011

Browse files
committed
Include calibration verdict
1 parent eafa78c commit e41b011

2 files changed

Lines changed: 82 additions & 7 deletions

File tree

cmd/cli.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,26 @@ func executeAnalysis(cmd *cobra.Command, args []string) error {
240240
}
241241

242242
if calibrate {
243+
summary := config.CalibrationSummary()
243244
cmd.Println("Calibration complete. Alerts suppressed; see logs for per-window metrics.")
245+
if summary.Windows == 0 {
246+
cmd.Println("Calibration summary: no complete windows were processed.")
247+
return nil
248+
}
249+
cmd.Printf("Calibration summary: %d window(s) analyzed\n", summary.Windows)
250+
cmd.Printf(
251+
"Recommended thresholds (based on max observed rates): packet-threshold >= %.4f, destination-threshold >= %.4f\n",
252+
summary.RecommendedPacketThreshold,
253+
summary.RecommendedDestinationThreshold,
254+
)
255+
if summary.MaxDestinationRate > 0 && summary.MaxDestination.IP != "" {
256+
cmd.Printf(
257+
"Top destination: %s (rate %.4f packets/s, %d packets)\n",
258+
summary.MaxDestination.String(),
259+
summary.MaxDestinationRate,
260+
summary.MaxDestinationPackets,
261+
)
262+
}
244263
return nil
245264
}
246265

internal/analysis_batch.go

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,23 @@ type AnalysisContext struct {
122122
}
123123

124124
type calibrationStats struct {
125-
windows int
126-
packetRateSum float64
127-
packetRateMax float64
128-
hostRateSum float64
129-
hostRateMax float64
125+
windows int
126+
packetRateSum float64
127+
packetRateMax float64
128+
hostRateSum float64
129+
hostRateMax float64
130+
topDestinationRateMax float64
131+
topDestinationCountMax int
132+
topDestinationCandidate Destination
130133
}
131134

132-
func (s *calibrationStats) update(packetRate float64, hostRate float64) {
135+
func (s *calibrationStats) update(
136+
packetRate float64,
137+
hostRate float64,
138+
topDestination Destination,
139+
topCount int,
140+
topRate float64,
141+
) {
133142
if s == nil {
134143
return
135144
}
@@ -142,6 +151,20 @@ func (s *calibrationStats) update(packetRate float64, hostRate float64) {
142151
if hostRate > s.hostRateMax {
143152
s.hostRateMax = hostRate
144153
}
154+
if topRate > s.topDestinationRateMax {
155+
s.topDestinationRateMax = topRate
156+
s.topDestinationCountMax = topCount
157+
s.topDestinationCandidate = topDestination
158+
return
159+
}
160+
if topRate == s.topDestinationRateMax && topRate > 0 {
161+
currentLabel := s.topDestinationCandidate.String()
162+
candidateLabel := topDestination.String()
163+
if currentLabel == "" || candidateLabel < currentLabel {
164+
s.topDestinationCountMax = topCount
165+
s.topDestinationCandidate = topDestination
166+
}
167+
}
145168
}
146169

147170
func (s *calibrationStats) packetRateAvg() float64 {
@@ -158,6 +181,19 @@ func (s *calibrationStats) hostRateAvg() float64 {
158181
return s.hostRateSum / float64(s.windows)
159182
}
160183

184+
type CalibrationSummary struct {
185+
Windows int
186+
PacketRateAvg float64
187+
PacketRateMax float64
188+
HostRateAvg float64
189+
HostRateMax float64
190+
RecommendedPacketThreshold float64
191+
RecommendedDestinationThreshold float64
192+
MaxDestination Destination
193+
MaxDestinationRate float64
194+
MaxDestinationPackets int
195+
}
196+
161197
func NewAnalysisConfiguration(
162198
srcIP string,
163199
c2IP string,
@@ -637,7 +673,7 @@ func (config *AnalysisConfiguration) logCalibration(windowEnd time.Time, duratio
637673
topLabel = topDestination.String()
638674
}
639675

640-
config.calibration.update(globalPacketRate, scanRate)
676+
config.calibration.update(globalPacketRate, scanRate, topDestination, topCount, topRate)
641677

642678
nullTestActivity := "idle"
643679
if config.result.globalPacketCount > 0 {
@@ -1015,6 +1051,26 @@ func (config *AnalysisConfiguration) Summary() AnalysisSummary {
10151051
return config.summary
10161052
}
10171053

1054+
func (config *AnalysisConfiguration) CalibrationSummary() CalibrationSummary {
1055+
if config == nil {
1056+
return CalibrationSummary{}
1057+
}
1058+
1059+
stats := config.calibration
1060+
return CalibrationSummary{
1061+
Windows: stats.windows,
1062+
PacketRateAvg: stats.packetRateAvg(),
1063+
PacketRateMax: stats.packetRateMax,
1064+
HostRateAvg: stats.hostRateAvg(),
1065+
HostRateMax: stats.hostRateMax,
1066+
RecommendedPacketThreshold: stats.topDestinationRateMax,
1067+
RecommendedDestinationThreshold: stats.hostRateMax,
1068+
MaxDestination: stats.topDestinationCandidate,
1069+
MaxDestinationRate: stats.topDestinationRateMax,
1070+
MaxDestinationPackets: stats.topDestinationCountMax,
1071+
}
1072+
}
1073+
10181074
func defaultCaptureBehavior(config *AnalysisConfiguration, behavior *Behavior) (bool, error) {
10191075
if config == nil {
10201076
return false, errors.New("config is nil")

0 commit comments

Comments
 (0)