Add LOGPile BMC diagnostic log analyzer
Features: - Modular parser architecture for vendor-specific formats - Inspur/Kaytus parser supporting asset.json, devicefrusdr.log, component.log, idl.log, and syslog files - PCI Vendor/Device ID lookup for hardware identification - Web interface with tabs: Events, Sensors, Config, Serials, Firmware - Server specification summary with component grouping - Export to CSV, JSON, TXT formats - BMC alarm parsing from IDL logs (memory errors, PSU events, etc.) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
106
internal/parser/registry.go
Normal file
106
internal/parser/registry.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
registry = make(map[string]VendorParser)
|
||||
registryLock sync.RWMutex
|
||||
)
|
||||
|
||||
// Register adds a vendor parser to the registry
|
||||
// Called from vendor module init() functions
|
||||
func Register(p VendorParser) {
|
||||
registryLock.Lock()
|
||||
defer registryLock.Unlock()
|
||||
|
||||
vendor := p.Vendor()
|
||||
if _, exists := registry[vendor]; exists {
|
||||
panic(fmt.Sprintf("parser already registered for vendor: %s", vendor))
|
||||
}
|
||||
registry[vendor] = p
|
||||
}
|
||||
|
||||
// GetParser returns parser for specific vendor
|
||||
func GetParser(vendor string) (VendorParser, bool) {
|
||||
registryLock.RLock()
|
||||
defer registryLock.RUnlock()
|
||||
|
||||
p, ok := registry[vendor]
|
||||
return p, ok
|
||||
}
|
||||
|
||||
// ListParsers returns list of all registered vendor names
|
||||
func ListParsers() []string {
|
||||
registryLock.RLock()
|
||||
defer registryLock.RUnlock()
|
||||
|
||||
vendors := make([]string, 0, len(registry))
|
||||
for v := range registry {
|
||||
vendors = append(vendors, v)
|
||||
}
|
||||
sort.Strings(vendors)
|
||||
return vendors
|
||||
}
|
||||
|
||||
// DetectResult holds detection result for a parser
|
||||
type DetectResult struct {
|
||||
Parser VendorParser
|
||||
Confidence int
|
||||
}
|
||||
|
||||
// DetectFormat tries to detect archive format and returns best matching parser
|
||||
func DetectFormat(files []ExtractedFile) (VendorParser, error) {
|
||||
registryLock.RLock()
|
||||
defer registryLock.RUnlock()
|
||||
|
||||
var results []DetectResult
|
||||
|
||||
for _, p := range registry {
|
||||
confidence := p.Detect(files)
|
||||
if confidence > 0 {
|
||||
results = append(results, DetectResult{
|
||||
Parser: p,
|
||||
Confidence: confidence,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(results) == 0 {
|
||||
return nil, fmt.Errorf("no parser found for this archive format")
|
||||
}
|
||||
|
||||
// Sort by confidence descending
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Confidence > results[j].Confidence
|
||||
})
|
||||
|
||||
return results[0].Parser, nil
|
||||
}
|
||||
|
||||
// DetectAllFormats returns all parsers that can handle the files with their confidence
|
||||
func DetectAllFormats(files []ExtractedFile) []DetectResult {
|
||||
registryLock.RLock()
|
||||
defer registryLock.RUnlock()
|
||||
|
||||
var results []DetectResult
|
||||
|
||||
for _, p := range registry {
|
||||
confidence := p.Detect(files)
|
||||
if confidence > 0 {
|
||||
results = append(results, DetectResult{
|
||||
Parser: p,
|
||||
Confidence: confidence,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Confidence > results[j].Confidence
|
||||
})
|
||||
|
||||
return results
|
||||
}
|
||||
Reference in New Issue
Block a user