aboutsummaryrefslogtreecommitdiffstats
path: root/modules/actions/log.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/actions/log.go')
-rw-r--r--modules/actions/log.go49
1 files changed, 47 insertions, 2 deletions
diff --git a/modules/actions/log.go b/modules/actions/log.go
index c38082b5dc..5a1425e031 100644
--- a/modules/actions/log.go
+++ b/modules/actions/log.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/models/dbfs"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/storage"
+ "code.gitea.io/gitea/modules/zstd"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"google.golang.org/protobuf/types/known/timestamppb"
@@ -28,6 +29,9 @@ const (
defaultBufSize = MaxLineSize
)
+// WriteLogs appends logs to DBFS file for temporary storage.
+// It doesn't respect the file format in the filename like ".zst", since it's difficult to reopen a closed compressed file and append new content.
+// Why doesn't it store logs in object storage directly? Because it's not efficient to append content to object storage.
func WriteLogs(ctx context.Context, filename string, offset int64, rows []*runnerv1.LogRow) ([]int, error) {
flag := os.O_WRONLY
if offset == 0 {
@@ -106,6 +110,17 @@ func ReadLogs(ctx context.Context, inStorage bool, filename string, offset, limi
return rows, nil
}
+const (
+ // logZstdBlockSize is the block size for zstd compression.
+ // 128KB leads the compression ratio to be close to the regular zstd compression.
+ // And it means each read from the underlying object storage will be at least 128KB*(compression ratio).
+ // The compression ratio is about 30% for text files, so the actual read size is about 38KB, which should be acceptable.
+ logZstdBlockSize = 128 * 1024 // 128KB
+)
+
+// TransferLogs transfers logs from DBFS to object storage.
+// It happens when the file is complete and no more logs will be appended.
+// It respects the file format in the filename like ".zst", and compresses the content if needed.
func TransferLogs(ctx context.Context, filename string) (func(), error) {
name := DBFSPrefix + filename
remove := func() {
@@ -119,7 +134,26 @@ func TransferLogs(ctx context.Context, filename string) (func(), error) {
}
defer f.Close()
- if _, err := storage.Actions.Save(filename, f, -1); err != nil {
+ var reader io.Reader = f
+ if strings.HasSuffix(filename, ".zst") {
+ r, w := io.Pipe()
+ reader = r
+ zstdWriter, err := zstd.NewSeekableWriter(w, logZstdBlockSize)
+ if err != nil {
+ return nil, fmt.Errorf("zstd NewSeekableWriter: %w", err)
+ }
+ go func() {
+ defer func() {
+ _ = w.CloseWithError(zstdWriter.Close())
+ }()
+ if _, err := io.Copy(zstdWriter, f); err != nil {
+ _ = w.CloseWithError(err)
+ return
+ }
+ }()
+ }
+
+ if _, err := storage.Actions.Save(filename, reader, -1); err != nil {
return nil, fmt.Errorf("storage save %q: %w", filename, err)
}
return remove, nil
@@ -150,11 +184,22 @@ func OpenLogs(ctx context.Context, inStorage bool, filename string) (io.ReadSeek
}
return f, nil
}
+
f, err := storage.Actions.Open(filename)
if err != nil {
return nil, fmt.Errorf("storage open %q: %w", filename, err)
}
- return f, nil
+
+ var reader io.ReadSeekCloser = f
+ if strings.HasSuffix(filename, ".zst") {
+ r, err := zstd.NewSeekableReader(f)
+ if err != nil {
+ return nil, fmt.Errorf("zstd NewSeekableReader: %w", err)
+ }
+ reader = r
+ }
+
+ return reader, nil
}
func FormatLog(timestamp time.Time, content string) string {