@@ -12,6 +12,7 @@ import (
1212 "github.com/docker/go-connections/nat"
1313 "github.com/google/uuid"
1414 tc "github.com/testcontainers/testcontainers-go"
15+ "golang.org/x/sync/errgroup"
1516 "io"
1617 "os"
1718 "os/exec"
@@ -21,6 +22,7 @@ import (
2122)
2223
2324const (
25+ EnvVarSaveLogs = "CTF_SAVE_LOGS"
2426 DefaultCTFLogsDir = "logs"
2527)
2628
@@ -230,6 +232,23 @@ func (dc *DockerClient) copyToContainer(containerID, sourceFile, targetPath stri
230232 return nil
231233}
232234
235+ func in (s string , substrings []string ) bool {
236+ for _ , substr := range substrings {
237+ if strings .Contains (s , substr ) {
238+ return true
239+ }
240+ }
241+ return false
242+ }
243+
244+ func isLocalToolDockerContainer (containerName string ) bool {
245+ if in (containerName , []string {"/sig-provider" , "/stats" , "/stats-db" , "/db" , "/backend" , "/promtail" , "/compose" , "/blockscout" , "/frontend" , "/user-ops-indexer" , "/visualizer" , "/redis-db" , "/proxy" }) {
246+ L .Debug ().Str ("Container" , containerName ).Msg ("Ignoring local tool container output" )
247+ return true
248+ }
249+ return false
250+ }
251+
233252// WriteAllContainersLogs writes all Docker container logs to the default logs directory
234253func WriteAllContainersLogs () error {
235254 L .Info ().Msg ("Writing Docker containers logs" )
@@ -247,49 +266,58 @@ func WriteAllContainersLogs() error {
247266 return fmt .Errorf ("failed to list Docker containers: %w" , err )
248267 }
249268
269+ eg := & errgroup.Group {}
270+
250271 for _ , containerInfo := range containers {
251- containerName := containerInfo .Names [0 ]
252- logOptions := container.LogsOptions {ShowStdout : true , ShowStderr : true }
253- logs , err := provider .Client ().ContainerLogs (context .Background (), containerInfo .ID , logOptions )
254- if err != nil {
255- L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to fetch logs for container" )
256- continue
257- }
258- logFilePath := filepath .Join (DefaultCTFLogsDir , fmt .Sprintf ("%s.log" , containerName ))
259- logFile , err := os .Create (logFilePath )
260- if err != nil {
261- L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to create container log file" )
262- continue
263- }
264- // Parse and write logs
265- header := make ([]byte , 8 ) // Docker stream header is 8 bytes
266- for {
267- _ , err := io .ReadFull (logs , header )
268- if err == io .EOF {
269- break
272+ eg .Go (func () error {
273+ containerName := containerInfo .Names [0 ]
274+ if isLocalToolDockerContainer (containerName ) {
275+ return nil
270276 }
277+ L .Debug ().Str ("Container" , containerName ).Msg ("Collecting logs" )
278+ logOptions := container.LogsOptions {ShowStdout : true , ShowStderr : true }
279+ logs , err := provider .Client ().ContainerLogs (context .Background (), containerInfo .ID , logOptions )
271280 if err != nil {
272- L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to read log stream header " )
273- break
281+ L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to fetch logs for container " )
282+ return err
274283 }
275-
276- // Extract log message size
277- msgSize := binary .BigEndian .Uint32 (header [4 :8 ])
278-
279- // Read the log message
280- msg := make ([]byte , msgSize )
281- _ , err = io .ReadFull (logs , msg )
284+ logFilePath := filepath .Join (DefaultCTFLogsDir , fmt .Sprintf ("%s.log" , containerName ))
285+ logFile , err := os .Create (logFilePath )
282286 if err != nil {
283- L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to read log message " )
284- break
287+ L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to create container log file " )
288+ return err
285289 }
290+ // Parse and write logs
291+ header := make ([]byte , 8 ) // Docker stream header is 8 bytes
292+ for {
293+ _ , err := io .ReadFull (logs , header )
294+ if err == io .EOF {
295+ break
296+ }
297+ if err != nil {
298+ L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to read log stream header" )
299+ break
300+ }
286301
287- // Write the log message to the file
288- if _ , err := logFile .Write (msg ); err != nil {
289- L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to write log message to file" )
290- break
302+ // Extract log message size
303+ msgSize := binary .BigEndian .Uint32 (header [4 :8 ])
304+
305+ // Read the log message
306+ msg := make ([]byte , msgSize )
307+ _ , err = io .ReadFull (logs , msg )
308+ if err != nil {
309+ L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to read log message" )
310+ break
311+ }
312+
313+ // Write the log message to the file
314+ if _ , err := logFile .Write (msg ); err != nil {
315+ L .Error ().Err (err ).Str ("Container" , containerName ).Msg ("failed to write log message to file" )
316+ break
317+ }
291318 }
292- }
319+ return nil
320+ })
293321 }
294- return nil
322+ return eg . Wait ()
295323}
0 commit comments