@@ -142,31 +142,51 @@ func main() {
142142 signalCh := make (chan os.Signal , 1 )
143143 signal .Notify (signalCh , os .Interrupt , syscall .SIGTERM , syscall .SIGINT )
144144
145- // Create a ticker to process the map every second
146- ticker := time .NewTicker (1 * time .Second )
147- defer ticker .Stop ()
148-
149145 // Set up signal handler
150146 go func () {
151147 s := <- signalCh
152148 _ , _ = fmt .Fprintf (os .Stderr , "Received %v signal, exiting...\n " , s )
153149 cancel ()
154150 }()
155151
156- // Create DNS lookup map and mutex for sharing between goroutines
157- dnsLookupMap := make (map [uint32 ]string )
158- dnsLookupMapMutex := & sync.RWMutex {}
152+ wg := & sync.WaitGroup {}
153+ outputCh := make (chan []statEntry )
154+ go outputEvents (outputCh )
155+ defer close (outputCh )
159156
160157 udpPktReader , err := ringbuf .NewReader (objs .UdpPkts )
161158 if err != nil {
162159 log .Printf ("Failed to create ringbuf reader for UDP packets: %v" , err )
163160 } else {
164161 log .Printf ("Created UDP packet ringbuf reader successfully" )
165- go processUDPPackets (ctx , udpPktReader )
166- defer udpPktReader .Close ()
162+ wg .Go (func () {
163+ go func () {
164+ <- ctx .Done ()
165+ udpPktReader .Close ()
166+ }()
167+
168+ processUDPPackets (ctx , udpPktReader , outputCh )
169+ })
167170 }
168171
169172 // Run the main loop
173+ wg .Go (func () {
174+ processPktCountMap (ctx , & objs , outputCh )
175+ })
176+
177+ wg .Wait ()
178+ }
179+
180+ // processPktCountMap starts processing the PktCount map for connection events
181+ func processPktCountMap (ctx context.Context , objs * counterObjects , outputCh chan <- []statEntry ) {
182+ // Create a ticker to process the map every second
183+ ticker := time .NewTicker (1 * time .Second )
184+ defer ticker .Stop ()
185+
186+ // Create DNS lookup map and mutex for sharing between goroutines
187+ dnsLookupMap := make (map [uint32 ]string )
188+ dnsLookupMapMutex := & sync.RWMutex {}
189+
170190 seenEntries := make (map [string ]bool )
171191 for {
172192 select {
@@ -226,23 +246,41 @@ func main() {
226246 continue
227247 }
228248
229- // Format output as JSON Lines
230- output := outputJSON (newEntries )
231-
232- // Add newline if needed
233- if output != "" && ! strings .HasSuffix (output , "\n " ) {
234- output += "\n "
235- }
236-
237- // Write output to stdout
238- fmt .Print (output )
249+ outputCh <- newEntries
239250
240251 case <- ctx .Done ():
241252 return
242253 }
243254 }
244255}
245256
257+ func outputEvents (ch <- chan []statEntry ) {
258+ numEvents := 0
259+
260+ for entries := range ch {
261+ if maxEvents > 0 && numEvents >= maxEvents {
262+ continue
263+ }
264+ // Format output as JSON Lines
265+ output := outputJSON (entries )
266+
267+ // Add newline if needed
268+ if output != "" && ! strings .HasSuffix (output , "\n " ) {
269+ output += "\n "
270+ }
271+
272+ // Write output to stdout
273+ fmt .Print (output )
274+
275+ if maxEvents > 0 {
276+ numEvents += len (entries )
277+ if numEvents >= maxEvents {
278+ log .Printf ("Max number of events has been met, no longer outputting any events" )
279+ }
280+ }
281+ }
282+ }
283+
246284// startKProbes attaches a series of eBPF programs to kernel functions using KProbes.
247285//
248286// This function iterates over a slice of kprobeHook structs, each containing a kernel function
0 commit comments