feat(inspur_legacy): new parser for pre-Kaytus Inspur onekeylog
Older AMI-BMC Inspur onekeylog archives (NF5466M5 / NF5280M5 generation)
opened to an empty result: they carry none of the files the inspur parser
keys on (no asset.json, devicefrusdr.log, selelist.csv or component.log).
New package internal/parser/vendors/inspur_legacy (vendor id inspur_legacy),
separate from inspur:
- binary IPMI FRU decode (FRU.bin) -> board identity
- Inspur_AssetInfoInventory.log -> CPU / memory / PCIe / PSU inventory
- events from Inspur_<model>_<serial>_IDL, sel.log, blackbox.log,
MegaRAID raid0.log, and the flat AMI <severity>.log files
- no live sensors in this archive class -> recorded as a collection error
- BMC clock timestamps before 2010 dropped as un-set (1970 / ~2005 RTC)
Registry: add optional PrioritizedParser { DetectPriority() int } so a
confidence tie is broken by specificity. inspur_legacy returns 10 and also
declines (Detect 0) when modern Kaytus markers are present, so the two
Inspur parsers never fight over a newer dump.
Docs: ADL-065, 06-parsers.md, releases/v1.32.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017VL8wLGD6Lnp6hZCpqT6cZ
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
be37f1852b
commit
3311bafd8e
+54
@@ -0,0 +1,54 @@
|
||||
package inspurlegacy
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.mchus.pro/mchus/logpile/internal/models"
|
||||
)
|
||||
|
||||
// bogusYear reports whether a timestamp comes from an AMI BMC clock that had
|
||||
// not yet been set: the 1970/1971 epoch, or the ~2005 firmware-default RTC seen
|
||||
// in alert.log. This hardware shipped no earlier than 2018, so any event before
|
||||
// 2010 has no trustworthy wall-clock time.
|
||||
func bogusYear(t time.Time) bool { return t.Year() < 2010 }
|
||||
|
||||
// severityFromWord maps a free-text severity/class word to models.Severity.
|
||||
func severityFromWord(s string) models.Severity {
|
||||
switch strings.ToLower(strings.TrimSpace(s)) {
|
||||
case "critical", "error", "fatal", "serious", "nonrecoverable", "non-recoverable":
|
||||
return models.SeverityCritical
|
||||
case "warning", "warn", "predictive":
|
||||
return models.SeverityWarning
|
||||
default:
|
||||
return models.SeverityInfo
|
||||
}
|
||||
}
|
||||
|
||||
// dedupeEvents removes exact duplicates (same timestamp, source, description)
|
||||
// in place, preserving order. The same fault is often reported by both the IDL
|
||||
// log and sel.log.
|
||||
func dedupeEvents(events []models.Event) []models.Event {
|
||||
seen := make(map[string]struct{}, len(events))
|
||||
out := events[:0]
|
||||
for _, e := range events {
|
||||
key := e.Timestamp.Format(time.RFC3339) + "|" + e.Source + "|" + e.SensorName + "|" + e.Description
|
||||
if _, ok := seen[key]; ok {
|
||||
continue
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, e)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// sortEvents orders events chronologically, then by source for stability.
|
||||
func sortEvents(events []models.Event) {
|
||||
sort.SliceStable(events, func(i, j int) bool {
|
||||
if !events[i].Timestamp.Equal(events[j].Timestamp) {
|
||||
return events[i].Timestamp.Before(events[j].Timestamp)
|
||||
}
|
||||
return events[i].Source < events[j].Source
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user