Skip to content

Commit dee8fee

Browse files
committed
auditbeat: Update to quark 0.6.0
Mostly keeping track of API changes, while here add some more members to the metrics.
1 parent 19d43cf commit dee8fee

7 files changed

Lines changed: 116 additions & 147 deletions

File tree

NOTICE.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12840,11 +12840,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1284012840

1284112841
--------------------------------------------------------------------------------
1284212842
Dependency : github.com/elastic/go-quark
12843-
Version: v0.3.0
12843+
Version: v0.6.0
1284412844
Licence type (autodetected): Apache-2.0
1284512845
--------------------------------------------------------------------------------
1284612846

12847-
Contents of probable licence file $GOMODCACHE/github.com/elastic/go-quark@v0.3.0/LICENSE.txt:
12847+
Contents of probable licence file $GOMODCACHE/github.com/elastic/go-quark@v0.6.0/LICENSE.txt:
1284812848

1284912849

1285012850
Apache License
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: enhancement
2+
summary: update quark to 0.6.0
3+
component: auditbeat

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ require (
175175
github.com/elastic/elastic-agent-system-metrics v0.14.4
176176
github.com/elastic/go-elasticsearch/v8 v8.19.0
177177
github.com/elastic/go-freelru v0.16.0
178-
github.com/elastic/go-quark v0.3.0
178+
github.com/elastic/go-quark v0.6.0
179179
github.com/elastic/go-sfdc v0.0.0-20260504130806-a46e22d049d9
180180
github.com/elastic/mito v1.27.0
181181
github.com/elastic/mock-es v0.0.0-20250530054253-8c3b6053f9b6

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,8 @@ github.com/elastic/go-lumber v0.2.0 h1:BVGh+jq6tmp5ajAQ4QaPLcwC8vYqQ0yzt0tmWfuz7
411411
github.com/elastic/go-lumber v0.2.0/go.mod h1:HHaWnZamYKWsR9/eZNHqRHob8iQDKnchHmmskT/SKko=
412412
github.com/elastic/go-perf v0.0.0-20260224073651-af0ee0c731b7 h1:fGi5uudj7m5O1RgQl+bSZmwlqvuUMEi97X7TzWBOMGk=
413413
github.com/elastic/go-perf v0.0.0-20260224073651-af0ee0c731b7/go.mod h1:ucTo2u8JvFyIPQOaRlX7aVF0d3wwmF1dy/PVp5GUHZI=
414-
github.com/elastic/go-quark v0.3.0 h1:d4vokx0psEJo+93fnhvWpTJMggPd9rfMJSleoLva4xA=
415-
github.com/elastic/go-quark v0.3.0/go.mod h1:bO/XIGZBUJGxyiJ9FTsSYn9YlfOTRJnmOP+iBE2FyjA=
414+
github.com/elastic/go-quark v0.6.0 h1:ESbcnjLheNn3QNSCdwTcqV+z+IRKt5+UQ3LaoKv5DJs=
415+
github.com/elastic/go-quark v0.6.0/go.mod h1:bO/XIGZBUJGxyiJ9FTsSYn9YlfOTRJnmOP+iBE2FyjA=
416416
github.com/elastic/go-seccomp-bpf v1.5.0 h1:gJV+U1iP+YC70ySyGUUNk2YLJW5/IkEw4FZBJfW8ZZY=
417417
github.com/elastic/go-seccomp-bpf v1.5.0/go.mod h1:umdhQ/3aybliBF2jjiZwS492I/TOKz+ZRvsLT3hVe1o=
418418
github.com/elastic/go-sfdc v0.0.0-20260504130806-a46e22d049d9 h1:UbquKP8gHTRugCZQ/KoVQrz8XnHzncsrHFfgTa+PfTg=

x-pack/auditbeat/module/system/process/quark_provider_linux.go

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ import (
2323
)
2424

2525
var quarkMetrics = struct {
26-
insertions *monitoring.Uint
27-
removals *monitoring.Uint
28-
aggregations *monitoring.Uint
29-
nonAggregations *monitoring.Uint
30-
lost *monitoring.Uint
31-
backend *monitoring.String
26+
insertions *monitoring.Uint
27+
removals *monitoring.Uint
28+
aggregations *monitoring.Uint
29+
nonAggregations *monitoring.Uint
30+
garbageCollections *monitoring.Uint
31+
lost *monitoring.Uint
32+
backend *monitoring.String
3233
}{}
3334

3435
func init() {
@@ -37,6 +38,7 @@ func init() {
3738
quarkMetrics.removals = monitoring.NewUint(reg, "removals")
3839
quarkMetrics.aggregations = monitoring.NewUint(reg, "aggregations")
3940
quarkMetrics.nonAggregations = monitoring.NewUint(reg, "non_aggregations")
41+
quarkMetrics.garbageCollections = monitoring.NewUint(reg, "garbage_collections")
4042
quarkMetrics.lost = monitoring.NewUint(reg, "lost")
4143
quarkMetrics.backend = monitoring.NewString(reg, "backend", monitoring.Report)
4244
}
@@ -65,7 +67,7 @@ func NewFromQuark(ms MetricSet) (mb.MetricSet, error) {
6567
if err != nil {
6668
return nil, fmt.Errorf("failed to fetch self mount inode: %w", err)
6769
}
68-
qm.selfMntNsIno = uint32(ino64)
70+
qm.selfMntNsIno = uint32(ino64) //nolint:gosec // mount namespace inodes fit in uint32
6971
qm.cachedHasher, err = hasher.NewFileHasherWithCache(qm.config.HasherConfig, 4096)
7072
if err != nil {
7173
return nil, fmt.Errorf("can't create hash cache: %w", err)
@@ -76,17 +78,18 @@ func NewFromQuark(ms MetricSet) (mb.MetricSet, error) {
7678
attr.Flags &= ^quark.QQ_ALL_BACKENDS
7779
attr.Flags |= quark.QQ_KPROBE
7880
}
79-
qm.queue, err = quark.OpenQueue(attr, 1)
81+
qm.queue, err = quark.OpenQueue(attr)
8082
if err != nil {
8183
qm.cachedHasher.Close()
8284
return nil, fmt.Errorf("can't open quark queue: %w", err)
8385
}
8486
stats := qm.queue.Stats()
85-
if stats.Backend == quark.QQ_EBPF {
87+
switch stats.Backend {
88+
case quark.QQ_EBPF:
8689
qm.log.Info("quark using EBPF")
87-
} else if stats.Backend == quark.QQ_KPROBE {
90+
case quark.QQ_KPROBE:
8891
qm.log.Info("quark using KPROBES")
89-
} else {
92+
default:
9093
qm.queue.Close()
9194
qm.cachedHasher.Close()
9295
return nil, fmt.Errorf("quark has an invalid backend")
@@ -103,6 +106,14 @@ func (ms *QuarkMetricSet) Run(r mb.PushReporterV2) {
103106

104107
metricsStamp := time.Now()
105108

109+
for _, proc := range ms.queue.Snapshot() {
110+
var fakeEvent quark.Event
111+
fakeEvent.Process = proc
112+
if event, ok := ms.toEvent(fakeEvent, true); ok {
113+
r.Event(event)
114+
}
115+
}
116+
106117
MainLoop:
107118
for {
108119
// Poll for done
@@ -115,29 +126,20 @@ MainLoop:
115126
ms.maybeUpdateMetrics(&metricsStamp)
116127

117128
x := time.Now()
118-
quarkEvents, err := ms.queue.GetEvents()
119-
if len(quarkEvents) == 1 {
120-
ms.log.Debugf("getevents took %v", time.Since(x))
121-
}
122-
if err != nil {
123-
ms.log.Error("quark GetEvents, unrecoverable error", err)
124-
break MainLoop
125-
}
126-
if len(quarkEvents) == 0 {
127-
err = ms.queue.Block()
128-
if err != nil {
129+
quarkEvent, ok := ms.queue.GetEvent()
130+
if !ok {
131+
if err := ms.queue.Block(); err != nil {
129132
ms.log.Error("quark Block, unrecoverable error", err)
130133
break MainLoop
131134
}
132135
continue
133136
}
134-
for _, quarkEvent := range quarkEvents {
135-
if !wantedEvent(quarkEvent) {
136-
continue
137-
}
138-
if event, ok := ms.toEvent(quarkEvent); ok {
139-
r.Event(event)
140-
}
137+
ms.log.Debugf("getevent took %v", time.Since(x))
138+
if !wantedEvent(quarkEvent) {
139+
continue
140+
}
141+
if event, ok := ms.toEvent(quarkEvent, false); ok {
142+
r.Event(event)
141143
}
142144
}
143145

@@ -150,8 +152,8 @@ MainLoop:
150152

151153
// toEvent converts a quark.Event to a mb.Event, returns true if we
152154
// were able to make an event.
153-
func (ms *QuarkMetricSet) toEvent(quarkEvent quark.Event) (mb.Event, bool) {
154-
action, evtype := actionAndTypeOfEvent(quarkEvent)
155+
func (ms *QuarkMetricSet) toEvent(quarkEvent quark.Event, snap bool) (mb.Event, bool) {
156+
action, evtype := actionAndTypeOfEvent(quarkEvent, snap)
155157
process := quarkEvent.Process
156158
event := mb.Event{RootFields: mapstr.M{}}
157159

@@ -174,11 +176,17 @@ func (ms *QuarkMetricSet) toEvent(quarkEvent quark.Event) (mb.Event, bool) {
174176
event.RootFields.Put("event.kind", "event")
175177
// Fill out process.*
176178
event.RootFields.Put("process.name", process.Comm)
177-
event.RootFields.Put("process.args", process.Cmdline)
178-
event.RootFields.Put("process.args_count", len(process.Cmdline))
179+
if len(process.Cmdline) > 0 {
180+
event.RootFields.Put("process.args", process.Cmdline)
181+
event.RootFields.Put("process.args_count", len(process.Cmdline))
182+
}
179183
event.RootFields.Put("process.pid", process.Pid)
180-
event.RootFields.Put("process.working_directory", process.Cwd)
181-
event.RootFields.Put("process.executable", process.Filename)
184+
if len(process.Cwd) > 0 {
185+
event.RootFields.Put("process.working_directory", process.Cwd)
186+
}
187+
if len(process.Exe) > 0 {
188+
event.RootFields.Put("process.executable", process.Exe)
189+
}
182190
if process.Exit.Valid {
183191
event.RootFields.Put("process.exit_code", process.Exit.ExitCode)
184192
}
@@ -192,7 +200,7 @@ func (ms *QuarkMetricSet) toEvent(quarkEvent quark.Event) (mb.Event, bool) {
192200

193201
// Ids
194202
event.RootFields.Put("process.parent.pid", process.Proc.Ppid)
195-
startTime := time.Unix(0, int64(process.Proc.TimeBoot))
203+
startTime := time.Unix(0, int64(process.Proc.TimeBoot)) //nolint:gosec // TimeBoot is a nanosecond timestamp that fits in int64
196204
if ms.HostID() != "" {
197205
// TODO unify with sessionview and guarantee loss of precision
198206
event.RootFields.Put("process.entity_id",
@@ -235,11 +243,11 @@ func (ms *QuarkMetricSet) toEvent(quarkEvent quark.Event) (mb.Event, bool) {
235243
// the file. When quark is running on kprobes, there are
236244
// limitations concerning the full path of the filename, in
237245
// those cases, the path won't start with a slash.
238-
if process.Proc.MntInonum == ms.selfMntNsIno && len(process.Filename) > 0 && process.Filename[0] == '/' {
239-
hashes, err := ms.cachedHasher.HashFile(process.Filename)
246+
if process.Proc.MntInonum == ms.selfMntNsIno && len(process.Exe) > 0 && process.Exe[0] == '/' {
247+
hashes, err := ms.cachedHasher.HashFile(process.Exe)
240248
if err != nil {
241249
processErr = fmt.Errorf("failed to hash executable %v for PID %v: %w",
242-
process.Filename, process.Pid, err)
250+
process.Exe, process.Pid, err)
243251
ms.log.Warn(processErr.Error())
244252
} else {
245253
for hashType, digest := range hashes {
@@ -248,7 +256,7 @@ func (ms *QuarkMetricSet) toEvent(quarkEvent quark.Event) (mb.Event, bool) {
248256
}
249257
}
250258
} else {
251-
ms.log.Debugf("skipping hash %s (inonum %d vs %d)", process.Filename, process.Proc.MntInonum, ms.selfMntNsIno)
259+
ms.log.Debugf("skipping hash %s (inonum %d vs %d)", process.Exe, process.Proc.MntInonum, ms.selfMntNsIno)
252260
}
253261

254262
return event, true
@@ -258,8 +266,7 @@ func (ms *QuarkMetricSet) toEvent(quarkEvent quark.Event) (mb.Event, bool) {
258266
func wantedEvent(quarkEvent quark.Event) bool {
259267
const wanted uint64 = quark.QUARK_EV_FORK |
260268
quark.QUARK_EV_EXEC |
261-
quark.QUARK_EV_EXIT |
262-
quark.QUARK_EV_SNAPSHOT
269+
quark.QUARK_EV_EXIT
263270
if quarkEvent.Events&wanted == 0 ||
264271
quarkEvent.Process.Pid == 2 ||
265272
quarkEvent.Process.Proc.Ppid == 2 { // skip kthreads
@@ -271,8 +278,7 @@ func wantedEvent(quarkEvent quark.Event) bool {
271278
}
272279

273280
// actionAndTypeOfEvent computes eventAction and event.type out of a quark.Event.
274-
func actionAndTypeOfEvent(quarkEvent quark.Event) (eventAction, []string) {
275-
snap := quarkEvent.Events&quark.QUARK_EV_SNAPSHOT != 0
281+
func actionAndTypeOfEvent(quarkEvent quark.Event, snap bool) (eventAction, []string) {
276282
fork := quarkEvent.Events&quark.QUARK_EV_FORK != 0
277283
exec := quarkEvent.Events&quark.QUARK_EV_EXEC != 0
278284
exit := quarkEvent.Events&quark.QUARK_EV_EXIT != 0
@@ -324,12 +330,14 @@ func (ms *QuarkMetricSet) maybeUpdateMetrics(stamp *time.Time) {
324330
quarkMetrics.removals.Set(stats.Removals)
325331
quarkMetrics.aggregations.Set(stats.Aggregations)
326332
quarkMetrics.nonAggregations.Set(stats.NonAggregations)
333+
quarkMetrics.garbageCollections.Set(stats.GarbageCollections)
327334
quarkMetrics.lost.Set(stats.Lost)
328-
if stats.Backend == quark.QQ_EBPF {
335+
switch stats.Backend {
336+
case quark.QQ_EBPF:
329337
quarkMetrics.backend.Set("ebpf")
330-
} else if stats.Backend == quark.QQ_KPROBE {
338+
case quark.QQ_KPROBE:
331339
quarkMetrics.backend.Set("kprobe")
332-
} else {
340+
default:
333341
quarkMetrics.backend.Set("invalid")
334342
}
335343

0 commit comments

Comments
 (0)