feat(go): add bounded hot-path enrichment
This commit is contained in:
parent
538d1d954a
commit
fd2bbba0d7
6 changed files with 282 additions and 30 deletions
|
|
@ -17,6 +17,7 @@ import (
|
|||
"time"
|
||||
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/correlation"
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/enrich"
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/incident"
|
||||
"codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model"
|
||||
)
|
||||
|
|
@ -54,14 +55,15 @@ type Stats struct {
|
|||
}
|
||||
|
||||
type Store struct {
|
||||
Dir string
|
||||
ProcRoot string
|
||||
MaxCount int
|
||||
MaxAgeDays int
|
||||
Now func() time.Time
|
||||
Collect func(int) ProcessDetail
|
||||
ParentOf func(int) int
|
||||
Incidents *incident.Store
|
||||
Dir string
|
||||
ProcRoot string
|
||||
MaxCount int
|
||||
MaxAgeDays int
|
||||
Now func() time.Time
|
||||
Collect func(int) ProcessDetail
|
||||
ParentOf func(int) int
|
||||
Incidents *incident.Store
|
||||
LineageDepth int
|
||||
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
|
@ -97,7 +99,7 @@ func New(dir, procRoot string, maxCount, maxAgeDays int) (*Store, error) {
|
|||
if err := os.Remove(probePath); err != nil {
|
||||
return nil, fmt.Errorf("remove snapshot preflight: %w", err)
|
||||
}
|
||||
store := &Store{Dir: dir, ProcRoot: procRoot, MaxCount: maxCount, MaxAgeDays: maxAgeDays, Now: time.Now}
|
||||
store := &Store{Dir: dir, ProcRoot: procRoot, MaxCount: maxCount, MaxAgeDays: maxAgeDays, Now: time.Now, LineageDepth: 8}
|
||||
store.Collect = func(pid int) ProcessDetail { return collectProcess(procRoot, pid) }
|
||||
store.ParentOf = func(pid int) int { return readParent(procRoot, pid) }
|
||||
if err := store.Prune(); err != nil {
|
||||
|
|
@ -114,6 +116,7 @@ func (s *Store) ConfigureIncidents(enabled bool, window, lineageDepth int) error
|
|||
return err
|
||||
}
|
||||
s.Incidents = tracker
|
||||
s.LineageDepth = lineageDepth
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -160,9 +163,9 @@ func (s *Store) CaptureEvent(event map[string]any) (string, error) {
|
|||
report.Alerts = append(report.Alerts, alert)
|
||||
report.Severity = maxSeverity(report.Severity, alert.Severity)
|
||||
report.Processes = s.collectProcesses(report.Alerts)
|
||||
pids := alertPIDs(report.Alerts)
|
||||
lineage := correlation.LineageOf(pids, s.ParentOf, s.LineageDepth)
|
||||
if s.Incidents != nil {
|
||||
pids := alertPIDs(report.Alerts)
|
||||
lineage := correlation.LineageOf(pids, s.ParentOf, s.Incidents.Depth)
|
||||
preferred := ""
|
||||
if report.IncidentID != nil {
|
||||
preferred = *report.IncidentID
|
||||
|
|
@ -173,9 +176,7 @@ func (s *Store) CaptureEvent(event map[string]any) (string, error) {
|
|||
report.IncidentID = &id
|
||||
}
|
||||
}
|
||||
if report.Enrichment == nil {
|
||||
report.Enrichment = map[string]any{"source": "enodia-sentinel-go"}
|
||||
}
|
||||
report.Enrichment = enrich.Build(report.Alerts, enrichmentProcesses(report.Processes), lineageValues(lineage))
|
||||
if err := writeJSONAtomic(jsonPath, report); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -212,6 +213,28 @@ func alertPIDs(alerts []model.Alert) []int {
|
|||
return pids
|
||||
}
|
||||
|
||||
func enrichmentProcesses(processes []ProcessDetail) []enrich.Process {
|
||||
result := make([]enrich.Process, 0, len(processes))
|
||||
for _, process := range processes {
|
||||
result = append(result, enrich.Process{
|
||||
PID: process.PID, Comm: process.Comm, Exe: process.Exe,
|
||||
PPID: process.PPID, PPIDComm: process.PPIDComm,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func lineageValues(lineage map[int]bool) []int {
|
||||
result := make([]int, 0, len(lineage))
|
||||
for pid, included := range lineage {
|
||||
if included {
|
||||
result = append(result, pid)
|
||||
}
|
||||
}
|
||||
sort.Ints(result)
|
||||
return result
|
||||
}
|
||||
|
||||
// SnapshotStats prunes first, then derives status claims from retained,
|
||||
// parseable snapshot files. Calling it for every status emission keeps the age
|
||||
// bound active even when a quiet host produces no new alert snapshots.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue