@@ -23,12 +23,13 @@ import (
2323)
2424
2525var 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
3435func 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+
106117MainLoop:
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) {
258266func 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