@@ -279,34 +279,23 @@ func SaveContainerLogs(dir string) ([]string, error) {
279279 return nil , fmt .Errorf ("failed to create directory %s: %w" , dir , err )
280280 }
281281 }
282- provider , err := tc .NewDockerProvider ()
283- if err != nil {
284- return nil , fmt .Errorf ("failed to create Docker provider: %w" , err )
285- }
286- containers , err := provider .Client ().ContainerList (context .Background (), container.ListOptions {
282+
283+ logStream , lErr := StreamContainerLogs (container.ListOptions {
287284 All : true ,
288285 Filters : dfilter .NewArgs (dfilter.KeyValuePair {
289286 Key : "label" ,
290287 Value : "framework=ctf" ,
291288 }),
292- })
293- if err != nil {
294- return nil , fmt .Errorf ("failed to list Docker containers: %w" , err )
289+ }, container.LogsOptions {ShowStdout : true , ShowStderr : true })
290+
291+ if lErr != nil {
292+ return nil , lErr
295293 }
296294
297295 eg := & errgroup.Group {}
298296 logFilePaths := make ([]string , 0 )
299-
300- for _ , containerInfo := range containers {
297+ for containerName , reader := range logStream {
301298 eg .Go (func () error {
302- containerName := containerInfo .Names [0 ]
303- L .Debug ().Str ("Container" , containerName ).Msg ("Collecting logs" )
304- logOptions := container.LogsOptions {ShowStdout : true , ShowStderr : true }
305- logs , err := provider .Client ().ContainerLogs (context .Background (), containerInfo .ID , logOptions )
306- if err != nil {
307- L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to fetch logs for container" )
308- return err
309- }
310299 logFilePath := filepath .Join (dir , fmt .Sprintf ("%s.log" , containerName ))
311300 logFile , err := os .Create (logFilePath )
312301 if err != nil {
@@ -317,7 +306,7 @@ func SaveContainerLogs(dir string) ([]string, error) {
317306 // Parse and write logs
318307 header := make ([]byte , 8 ) // Docker stream header is 8 bytes
319308 for {
320- _ , err := io .ReadFull (logs , header )
309+ _ , err := io .ReadFull (reader , header )
321310 if err == io .EOF {
322311 break
323312 }
@@ -331,7 +320,7 @@ func SaveContainerLogs(dir string) ([]string, error) {
331320
332321 // Read the log message
333322 msg := make ([]byte , msgSize )
334- _ , err = io .ReadFull (logs , msg )
323+ _ , err = io .ReadFull (reader , msg )
335324 if err != nil {
336325 L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to read log message" )
337326 break
@@ -352,6 +341,54 @@ func SaveContainerLogs(dir string) ([]string, error) {
352341 return logFilePaths , nil
353342}
354343
344+ var ExitedCtfContainersListOpts = container.ListOptions {
345+ All : true ,
346+ Filters : dfilter .NewArgs (dfilter.KeyValuePair {
347+ Key : "label" ,
348+ Value : "framework=ctf" ,
349+ },
350+ dfilter.KeyValuePair {
351+ Key : "status" ,
352+ Value : "exited" },
353+ dfilter.KeyValuePair {
354+ Key : "status" ,
355+ Value : "dead" }),
356+ }
357+
358+ func StreamContainerLogs (listOptions container.ListOptions , logOptions container.LogsOptions ) (map [string ]io.ReadCloser , error ) {
359+ L .Info ().Msg ("Streaming Docker containers logs" )
360+ provider , err := tc .NewDockerProvider ()
361+ if err != nil {
362+ return nil , fmt .Errorf ("failed to create Docker provider: %w" , err )
363+ }
364+ containers , err := provider .Client ().ContainerList (context .Background (), listOptions )
365+ if err != nil {
366+ return nil , fmt .Errorf ("failed to list Docker containers: %w" , err )
367+ }
368+
369+ eg := & errgroup.Group {}
370+ logMap := make (map [string ]io.ReadCloser )
371+
372+ for _ , containerInfo := range containers {
373+ eg .Go (func () error {
374+ containerName := containerInfo .Names [0 ]
375+ L .Debug ().Str ("Container" , containerName ).Msg ("Collecting logs" )
376+ logs , err := provider .Client ().ContainerLogs (context .Background (), containerInfo .ID , logOptions )
377+ if err != nil {
378+ L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to fetch logs for container" )
379+ return err
380+ }
381+ logMap [containerName ] = logs
382+ return nil
383+ })
384+ }
385+ if err := eg .Wait (); err != nil {
386+ return nil , err
387+ }
388+
389+ return logMap , nil
390+ }
391+
355392func BuildImageOnce (once * sync.Once , dctx , dfile , nameAndTag string , buildArgs map [string ]string ) error {
356393 var err error
357394 once .Do (func () {
0 commit comments