Improve position validation logging and reduce spam
- Remove duplicate validation logging between mergeAircraftData and updateHistories - Add rate limiting: errors logged max once per 10 seconds per aircraft - Add rate limiting: warnings logged max once per 30 seconds per aircraft - Only log first error/warning message to reduce log verbosity - Clean up validation log entries when aircraft become stale - Maintain memory efficiency with automatic cleanup This significantly reduces log spam from aircraft with persistent position validation issues (e.g., CPR decoding problems). 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
94092298a1
commit
960f47682d
1 changed files with 23 additions and 20 deletions
|
|
@ -271,6 +271,7 @@ type Merger struct {
|
|||
historyLimit int // Maximum history points to retain
|
||||
staleTimeout time.Duration // Time before aircraft considered stale (15 seconds)
|
||||
updateMetrics map[uint32]*updateMetric // ICAO24 -> update rate calculation data
|
||||
validationLog map[uint32]time.Time // ICAO24 -> last validation log time (rate limiting)
|
||||
}
|
||||
|
||||
// updateMetric tracks recent update times for calculating update rates.
|
||||
|
|
@ -301,6 +302,7 @@ func NewMerger() (*Merger, error) {
|
|||
historyLimit: 500,
|
||||
staleTimeout: 15 * time.Second, // Aircraft timeout - reasonable for ADS-B tracking
|
||||
updateMetrics: make(map[uint32]*updateMetric),
|
||||
validationLog: make(map[uint32]time.Time),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -453,10 +455,14 @@ func (m *Merger) mergeAircraftData(state *AircraftState, new *modes.Aircraft, so
|
|||
validation := m.validatePosition(new, state, timestamp)
|
||||
|
||||
if !validation.Valid {
|
||||
// Log validation errors and skip position update
|
||||
icaoHex := fmt.Sprintf("%06X", new.ICAO24)
|
||||
for _, err := range validation.Errors {
|
||||
log.Printf("[POSITION_VALIDATION] ICAO %s: REJECTED position update - %s", icaoHex, err)
|
||||
// Rate-limited logging: only log once every 10 seconds per aircraft
|
||||
if lastLog, exists := m.validationLog[new.ICAO24]; !exists || timestamp.Sub(lastLog) > 10*time.Second {
|
||||
icaoHex := fmt.Sprintf("%06X", new.ICAO24)
|
||||
// Only log first error to reduce spam
|
||||
if len(validation.Errors) > 0 {
|
||||
log.Printf("[POSITION_VALIDATION] ICAO %s: REJECTED - %s", icaoHex, validation.Errors[0])
|
||||
m.validationLog[new.ICAO24] = timestamp
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Position is valid, proceed with normal logic
|
||||
|
|
@ -483,10 +489,15 @@ func (m *Merger) mergeAircraftData(state *AircraftState, new *modes.Aircraft, so
|
|||
}
|
||||
}
|
||||
|
||||
// Log warnings even if position is valid
|
||||
for _, warning := range validation.Warnings {
|
||||
icaoHex := fmt.Sprintf("%06X", new.ICAO24)
|
||||
log.Printf("[POSITION_VALIDATION] ICAO %s: WARNING - %s", icaoHex, warning)
|
||||
// Rate-limited warning logging
|
||||
if len(validation.Warnings) > 0 {
|
||||
// Only log warnings once every 30 seconds per aircraft
|
||||
warningKey := new.ICAO24 + 0x10000000 // Offset to differentiate from error logging
|
||||
if lastLog, exists := m.validationLog[warningKey]; !exists || timestamp.Sub(lastLog) > 30*time.Second {
|
||||
icaoHex := fmt.Sprintf("%06X", new.ICAO24)
|
||||
log.Printf("[POSITION_VALIDATION] ICAO %s: WARNING - %s", icaoHex, validation.Warnings[0])
|
||||
m.validationLog[warningKey] = timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -611,19 +622,8 @@ func (m *Merger) updateHistories(state *AircraftState, aircraft *modes.Aircraft,
|
|||
Longitude: aircraft.Longitude,
|
||||
Source: sourceID,
|
||||
})
|
||||
} else {
|
||||
// Log validation errors for debugging
|
||||
icaoHex := fmt.Sprintf("%06X", aircraft.ICAO24)
|
||||
for _, err := range validation.Errors {
|
||||
log.Printf("[POSITION_VALIDATION] ICAO %s: REJECTED - %s", icaoHex, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Log warnings even for valid positions
|
||||
for _, warning := range validation.Warnings {
|
||||
icaoHex := fmt.Sprintf("%06X", aircraft.ICAO24)
|
||||
log.Printf("[POSITION_VALIDATION] ICAO %s: WARNING - %s", icaoHex, warning)
|
||||
}
|
||||
// Note: Validation errors/warnings are already logged in mergeAircraftData
|
||||
}
|
||||
|
||||
// Signal history
|
||||
|
|
@ -847,6 +847,9 @@ func (m *Merger) CleanupStale() {
|
|||
if now.Sub(state.LastUpdate) > m.staleTimeout {
|
||||
delete(m.aircraft, icao)
|
||||
delete(m.updateMetrics, icao)
|
||||
// Clean up validation log entries
|
||||
delete(m.validationLog, icao)
|
||||
delete(m.validationLog, icao+0x10000000) // Warning key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue