Files
logpile/internal/parser/vendors/inspur/idl.go

122 lines
3.1 KiB
Go

package inspur
import (
"regexp"
"strings"
"time"
"git.mchus.pro/mchus/logpile/internal/models"
)
// ParseIDLLog parses IDL-style entries for BMC alarms.
// Works for both plain idl.log lines and JSON structured logs (idl_json/run_json)
// where MESSAGE/LOG2_FMTMSG contains:
// |timestamp|component|type|severity|eventID|description|
func ParseIDLLog(content []byte) []models.Event {
var events []models.Event
// Pattern to match CommerDiagnose log entries
// Example: |2025-12-02T17:54:27+08:00|MEMORY|Assert|Warning|0C180401|CPU1_C4D0 Memory Device Disabled...|
re := regexp.MustCompile(`\|(\d{4}-\d{2}-\d{2}T[\d:]+[+-]\d{2}:\d{2})\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|`)
lines := strings.Split(string(content), "\n")
seenEvents := make(map[string]bool) // Deduplicate events
for _, line := range lines {
matches := re.FindStringSubmatch(line)
if matches == nil {
continue
}
timestamp := matches[1]
component := matches[2]
eventType := matches[3]
severityStr := matches[4]
eventID := matches[5]
description := matches[6]
// Parse timestamp
ts, err := time.Parse("2006-01-02T15:04:05-07:00", timestamp)
if err != nil {
ts = time.Now()
}
// Map severity
severity := mapIDLSeverity(severityStr)
// Clean up description
description = cleanDescription(description)
// Create unique key for deduplication
eventKey := eventID + "|" + description
if seenEvents[eventKey] {
continue
}
seenEvents[eventKey] = true
// Extract sensor name from description if available
sensorName := extractSensorName(description, component)
events = append(events, models.Event{
ID: eventID,
Timestamp: ts,
Source: component,
SensorType: strings.ToLower(component),
SensorName: sensorName,
EventType: eventType,
Severity: severity,
Description: description,
})
}
return events
}
func mapIDLSeverity(s string) models.Severity {
switch strings.ToLower(s) {
case "critical", "error":
return models.SeverityCritical
case "warning":
return models.SeverityWarning
default:
return models.SeverityInfo
}
}
func cleanDescription(desc string) string {
// Remove trailing " - Assert" or similar
desc = strings.TrimSuffix(desc, " - Assert")
desc = strings.TrimSuffix(desc, " - Deassert")
desc = strings.TrimSpace(desc)
return desc
}
func extractSensorName(desc, component string) string {
// Try to extract sensor/device name from description
// For memory: CPU1_C4D0, CPU1_C4D1, etc.
if component == "MEMORY" {
re := regexp.MustCompile(`(CPU\d+_C\d+D\d+)`)
if matches := re.FindStringSubmatch(desc); matches != nil {
return matches[1]
}
}
// For PSU: PSU0, PSU1, etc.
if component == "PSU" || component == "POWER" {
re := regexp.MustCompile(`(PSU\d+)`)
if matches := re.FindStringSubmatch(desc); matches != nil {
return matches[1]
}
}
// For temperature sensors
if component == "TEMPERATURE" || component == "THERMAL" {
re := regexp.MustCompile(`(\w+_Temp|\w+_DTS)`)
if matches := re.FindStringSubmatch(desc); matches != nil {
return matches[1]
}
}
return component
}