mirror of
https://github.com/hauler-dev/hauler.git
synced 2026-04-05 02:07:46 +00:00
* only ignore project-root/store not all store paths * remove embedded cosign binary in favor of fork library
100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
package log
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// CustomWriter forwards log messages to the application's logger
|
|
type CustomWriter struct {
|
|
logger Logger
|
|
level string
|
|
}
|
|
|
|
func (cw *CustomWriter) Write(p []byte) (n int, err error) {
|
|
message := strings.TrimSpace(string(p))
|
|
if message != "" {
|
|
if cw.level == "error" {
|
|
cw.logger.Errorf("%s", message)
|
|
} else if cw.level == "info" {
|
|
cw.logger.Infof("%s", message)
|
|
} else {
|
|
cw.logger.Debugf("%s", message)
|
|
}
|
|
}
|
|
return len(p), nil
|
|
}
|
|
|
|
// logStream reads lines from a reader and writes them to the provided writer
|
|
func logStream(reader io.Reader, customWriter *CustomWriter, wg *sync.WaitGroup) {
|
|
defer wg.Done()
|
|
|
|
scanner := bufio.NewScanner(reader)
|
|
for scanner.Scan() {
|
|
customWriter.Write([]byte(scanner.Text()))
|
|
}
|
|
if err := scanner.Err(); err != nil && err != io.EOF {
|
|
customWriter.logger.Errorf("error reading log stream: %v", err)
|
|
}
|
|
}
|
|
|
|
// CaptureOutput redirects stdout and stderr to custom loggers and executes the provided function
|
|
func CaptureOutput(logger Logger, debug bool, fn func() error) error {
|
|
// Create pipes for capturing stdout and stderr
|
|
stdoutReader, stdoutWriter, err := os.Pipe()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create stdout pipe: %w", err)
|
|
}
|
|
stderrReader, stderrWriter, err := os.Pipe()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create stderr pipe: %w", err)
|
|
}
|
|
|
|
// Save original stdout and stderr
|
|
origStdout := os.Stdout
|
|
origStderr := os.Stderr
|
|
|
|
// Redirect stdout and stderr
|
|
os.Stdout = stdoutWriter
|
|
os.Stderr = stderrWriter
|
|
|
|
// Use WaitGroup to wait for logging goroutines to finish
|
|
var wg sync.WaitGroup
|
|
wg.Add(2)
|
|
|
|
// Start logging goroutines
|
|
if !debug {
|
|
go logStream(stdoutReader, &CustomWriter{logger: logger, level: "info"}, &wg)
|
|
go logStream(stderrReader, &CustomWriter{logger: logger, level: "error"}, &wg)
|
|
} else {
|
|
go logStream(stdoutReader, &CustomWriter{logger: logger, level: "debug"}, &wg)
|
|
go logStream(stderrReader, &CustomWriter{logger: logger, level: "debug"}, &wg)
|
|
}
|
|
|
|
// Run the provided function in a separate goroutine
|
|
fnErr := make(chan error, 1)
|
|
go func() {
|
|
fnErr <- fn()
|
|
stdoutWriter.Close() // Close writers to signal EOF to readers
|
|
stderrWriter.Close()
|
|
}()
|
|
|
|
// Wait for logging goroutines to finish
|
|
wg.Wait()
|
|
|
|
// Restore original stdout and stderr
|
|
os.Stdout = origStdout
|
|
os.Stderr = origStderr
|
|
|
|
// Check for errors from the function
|
|
if err := <-fnErr; err != nil {
|
|
return fmt.Errorf("function execution failed: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|