v1.3.0: Add multiple vendor parsers and enhanced hardware detection
New parsers: - NVIDIA Field Diagnostics parser with dmidecode output support - NVIDIA Bug Report parser with comprehensive hardware extraction - Supermicro crashdump (CDump.txt) parser - Generic fallback parser for unrecognized text files Enhanced GPU parsing (nvidia-bug-report): - Model and manufacturer detection (NVIDIA H100 80GB HBM3) - UUID, Video BIOS version, IRQ information - Bus location (BDF), DMA size/mask, device minor - PCIe bus type details New hardware detection (nvidia-bug-report): - System Information: server S/N, UUID, manufacturer, product name - CPU: model, S/N, cores, threads, frequencies from dmidecode - Memory: P/N, S/N, manufacturer, speed for all DIMMs - Power Supplies: manufacturer, model, S/N, wattage, status - Network Adapters: Ethernet/InfiniBand controllers with VPD data - Model, P/N, S/N from lspci Vital Product Data - Port count/type detection (QSFP56, OSFP, etc.) - Support for ConnectX-6/7 adapters Archive handling improvements: - Plain .gz file support (not just tar.gz) - Increased size limit for plain gzip files (50MB) - Better error handling for mixed archive formats Web interface enhancements: - Display parser name and filename badges - Improved file info section with visual indicators Co-Authored-By: Claude (qwen3-coder:480b) <noreply@anthropic.com>
This commit is contained in:
72
internal/parser/vendors/generic/README.md
vendored
Normal file
72
internal/parser/vendors/generic/README.md
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
# Generic Text File Parser
|
||||
|
||||
Fallback парсер для текстовых файлов, которые не распознаны другими парсерами.
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот парсер обрабатывает любые текстовые файлы, которые:
|
||||
- Не являются архивами специфичных вендоров
|
||||
- Содержат текстовую информацию (не бинарные данные)
|
||||
- Представляют собой одиночные .gz файлы или простые текстовые файлы
|
||||
|
||||
## Приоритет
|
||||
|
||||
**Confidence score: 15** (низкий приоритет)
|
||||
|
||||
Этот парсер срабатывает только если ни один другой парсер не подошел с более высоким confidence.
|
||||
|
||||
## Поддерживаемые файлы
|
||||
|
||||
### Автоматически распознаваемые типы
|
||||
|
||||
1. **NVIDIA Bug Report** (`nvidia-bug-report-*.log.gz`)
|
||||
- Извлекает информацию о драйвере NVIDIA
|
||||
- Находит GPU устройства
|
||||
- Показывает версию драйвера
|
||||
|
||||
2. **Любые текстовые файлы**
|
||||
- Проверяет, что содержимое - текст (не бинарные данные)
|
||||
- Показывает базовую информацию о файле
|
||||
|
||||
## Извлекаемые данные
|
||||
|
||||
### Events
|
||||
|
||||
- **Text File**: Базовая информация о загруженном файле
|
||||
- **Driver Info**: Информация о NVIDIA драйвере (для nvidia-bug-report)
|
||||
- **GPU Device**: Обнаруженные GPU устройства (для nvidia-bug-report)
|
||||
|
||||
## Пример использования
|
||||
|
||||
```bash
|
||||
# Запуск с nvidia-bug-report
|
||||
./logpile --file nvidia-bug-report-*.log.gz
|
||||
|
||||
# Запуск с любым текстовым файлом
|
||||
./logpile --file system.log.gz
|
||||
```
|
||||
|
||||
## Версионирование
|
||||
|
||||
**Текущая версия парсера:** 1.0.0
|
||||
|
||||
## Ограничения
|
||||
|
||||
1. Этот парсер предоставляет только базовую информацию
|
||||
2. Не выполняет глубокий анализ содержимого
|
||||
3. Для детального анализа специфичных логов рекомендуется создать dedicated парсер
|
||||
|
||||
## Расширение
|
||||
|
||||
Чтобы добавить поддержку нового типа файлов:
|
||||
|
||||
1. Добавьте проверку в функцию `Parse()`
|
||||
2. Создайте функцию `parseXXX()` для извлечения специфичной информации
|
||||
3. Увеличьте версию парсера
|
||||
|
||||
Пример:
|
||||
```go
|
||||
if strings.Contains(strings.ToLower(file.Path), "custom-log") {
|
||||
parseCustomLog(content, result)
|
||||
}
|
||||
```
|
||||
147
internal/parser/vendors/generic/parser.go
vendored
Normal file
147
internal/parser/vendors/generic/parser.go
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// Package generic provides a fallback parser for unrecognized text files
|
||||
package generic
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.mchus.pro/mchus/logpile/internal/models"
|
||||
"git.mchus.pro/mchus/logpile/internal/parser"
|
||||
)
|
||||
|
||||
// parserVersion - version of this parser module
|
||||
const parserVersion = "1.0.0"
|
||||
|
||||
func init() {
|
||||
parser.Register(&Parser{})
|
||||
}
|
||||
|
||||
// Parser implements VendorParser for generic text files
|
||||
type Parser struct{}
|
||||
|
||||
// Name returns human-readable parser name
|
||||
func (p *Parser) Name() string {
|
||||
return "Generic Text File Parser"
|
||||
}
|
||||
|
||||
// Vendor returns vendor identifier
|
||||
func (p *Parser) Vendor() string {
|
||||
return "generic"
|
||||
}
|
||||
|
||||
// Version returns parser version
|
||||
func (p *Parser) Version() string {
|
||||
return parserVersion
|
||||
}
|
||||
|
||||
// Detect checks if this is a text file (fallback with low confidence)
|
||||
// Returns confidence 0-100
|
||||
func (p *Parser) Detect(files []parser.ExtractedFile) int {
|
||||
// Only detect if there's exactly one file (plain .gz or single file)
|
||||
if len(files) != 1 {
|
||||
return 0
|
||||
}
|
||||
|
||||
file := files[0]
|
||||
|
||||
// Check if content looks like text (not binary)
|
||||
if !isLikelyText(file.Content) {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Return low confidence so other parsers have priority
|
||||
return 15
|
||||
}
|
||||
|
||||
// isLikelyText checks if content is likely text (not binary)
|
||||
func isLikelyText(content []byte) bool {
|
||||
// Check first 512 bytes for binary data
|
||||
sample := content
|
||||
if len(content) > 512 {
|
||||
sample = content[:512]
|
||||
}
|
||||
|
||||
binaryCount := 0
|
||||
for _, b := range sample {
|
||||
// Count non-printable characters (excluding common whitespace)
|
||||
if b < 32 && b != '\n' && b != '\r' && b != '\t' {
|
||||
binaryCount++
|
||||
}
|
||||
if b == 0 { // NULL byte is a strong indicator of binary
|
||||
binaryCount += 10
|
||||
}
|
||||
}
|
||||
|
||||
// If less than 5% binary, consider it text
|
||||
return binaryCount < len(sample)/20
|
||||
}
|
||||
|
||||
// Parse parses generic text file
|
||||
func (p *Parser) Parse(files []parser.ExtractedFile) (*models.AnalysisResult, error) {
|
||||
result := &models.AnalysisResult{
|
||||
Events: make([]models.Event, 0),
|
||||
FRU: make([]models.FRUInfo, 0),
|
||||
Sensors: make([]models.SensorReading, 0),
|
||||
}
|
||||
|
||||
// Initialize hardware config
|
||||
result.Hardware = &models.HardwareConfig{}
|
||||
|
||||
if len(files) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
file := files[0]
|
||||
content := string(file.Content)
|
||||
|
||||
// Create a single event with file info
|
||||
result.Events = append(result.Events, models.Event{
|
||||
Timestamp: time.Now(),
|
||||
Source: "File",
|
||||
EventType: "Text File",
|
||||
Description: "Generic text file loaded",
|
||||
Severity: models.SeverityInfo,
|
||||
RawData: "Filename: " + file.Path,
|
||||
})
|
||||
|
||||
// Try to extract some basic info from common file types
|
||||
if strings.Contains(strings.ToLower(file.Path), "nvidia-bug-report") {
|
||||
parseNvidiaBugReport(content, result)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// parseNvidiaBugReport extracts info from nvidia-bug-report files
|
||||
func parseNvidiaBugReport(content string, result *models.AnalysisResult) {
|
||||
lines := strings.Split(content, "\n")
|
||||
|
||||
// Look for GPU information
|
||||
for i, line := range lines {
|
||||
// Find NVIDIA driver version
|
||||
if strings.Contains(line, "NVRM version:") || strings.Contains(line, "nvidia-smi") {
|
||||
if i+5 < len(lines) {
|
||||
result.Events = append(result.Events, models.Event{
|
||||
Timestamp: time.Now(),
|
||||
Source: "NVIDIA Driver",
|
||||
EventType: "Driver Info",
|
||||
Description: "NVIDIA driver information found",
|
||||
Severity: models.SeverityInfo,
|
||||
RawData: strings.TrimSpace(line),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Find GPU devices
|
||||
if strings.Contains(line, "/proc/driver/nvidia/gpus/") && strings.Contains(line, "***") {
|
||||
result.Events = append(result.Events, models.Event{
|
||||
Timestamp: time.Now(),
|
||||
Source: "GPU",
|
||||
EventType: "GPU Device",
|
||||
Description: "GPU device detected",
|
||||
Severity: models.SeverityInfo,
|
||||
RawData: strings.TrimSpace(line),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user