Files
logpile/internal/parser/registry.go
Michael Chus 512957545a 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>
2026-01-25 04:11:23 +03:00

107 lines
2.3 KiB
Go

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
}