4.0 KiB
4.0 KiB
02 — Architecture
Runtime stack
| Layer | Technology |
|---|---|
| Language | Go 1.22+ |
| HTTP | net/http, http.ServeMux |
| UI | Embedded via //go:embed in web/embed.go (templates + static assets) |
| State | In-memory only — no database |
| Build | CGO_ENABLED=0, single static binary |
Default port: 8082
Directory structure
cmd/logpile/main.go # Binary entry point, CLI flag parsing
internal/
collector/ # Live data collectors
registry.go # Collector registration
redfish.go # Redfish connector (real implementation)
ipmi_mock.go # IPMI mock connector (scaffold)
types.go # Connector request/progress contracts
parser/ # Archive parsers
parser.go # BMCParser (dispatcher) + parse orchestration
archive.go # Archive extraction helpers
registry.go # Parser registry + detect/selection
interface.go # VendorParser interface
vendors/ # Vendor-specific parser modules
vendors.go # Import-side-effect registrations
inspur/
supermicro/
nvidia/
nvidia_bug_report/
unraid/
xigmanas/
generic/
pciids/ # PCI IDs lookup (embedded pci.ids)
server/ # HTTP layer
server.go # Server struct, route registration
handlers.go # All HTTP handler functions
exporter/ # Export formatters
exporter.go # CSV + JSON exporters
reanimator_models.go
reanimator_converter.go
models/ # Shared data contracts
web/
embed.go # go:embed directive
templates/ # HTML templates
static/ # JS / CSS
js/app.js # Frontend — API contract consumer
In-memory state
The Server struct in internal/server/server.go holds:
| Field | Type | Description |
|---|---|---|
result |
*models.AnalysisResult |
Current parsed/collected dataset |
detectedVendor |
string |
Vendor identifier from last parse |
jobManager |
*JobManager |
Tracks live collect job status/logs |
collectors |
*collector.Registry |
Registered live collection connectors |
State is replaced atomically on successful upload or collect.
On a failed/canceled collect, the previous result is preserved unchanged.
Upload flow (POST /api/upload)
multipart form field: "archive"
│
├─ file looks like JSON?
│ └─ parse as models.AnalysisResult snapshot → store in Server.result
│
└─ otherwise
└─ parser.NewBMCParser().ParseFromReader(...)
│
├─ try all registered vendor parsers (highest confidence wins)
└─ result → store in Server.result
Live collect flow (POST /api/collect)
validate request (host / protocol / port / username / auth_type / tls_mode)
│
└─ launch async job
│
├─ progress callback → job log (queryable via GET /api/collect/{id})
│
├─ success:
│ set source metadata (source_type=api, protocol, host, date)
│ store result in Server.result
│
└─ failure / cancel:
previous Server.result unchanged
Job lifecycle states: queued → running → success | failed | canceled
PCI IDs lookup
Load/override order (LOGPILE_PCI_IDS_PATH has highest priority because it is loaded last):
- Embedded
internal/parser/vendors/pciids/pci.ids(base dataset compiled into binary) ./pci.ids/usr/share/hwdata/pci.ids/usr/share/misc/pci.ids/opt/homebrew/share/pciids/pci.ids- Paths from
LOGPILE_PCI_IDS_PATH(colon-separated on Unix; later loaded, override same IDs)
This means unknown GPU/NIC model strings can be updated by refreshing pci.ids
without any code change.