Skip to content

Commit 8f85398

Browse files
committed
use ring buffer
1 parent 52e531e commit 8f85398

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

pkg/github/actions.go

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/json"
77
"fmt"
88
"net/http"
9+
"runtime"
910
"strconv"
1011
"strings"
1112

@@ -721,7 +722,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin
721722

722723
if returnContent {
723724
// Download and return the actual log content
724-
content, originalLength, httpResp, err := downloadLogContent(url.String(), tailLines) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp
725+
content, originalLength, httpResp, err := downloadLogContent(ctx, url.String(), tailLines) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp
725726
if err != nil {
726727
// To keep the return value consistent wrap the response as a GitHub Response
727728
ghRes := &github.Response{
@@ -742,8 +743,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin
742743
return result, resp, nil
743744
}
744745

745-
// downloadLogContent downloads the actual log content from a GitHub logs URL
746-
func downloadLogContent(logURL string, tailLines int) (string, int, *http.Response, error) {
746+
func downloadLogContent(ctx context.Context, logURL string, tailLines int) (string, int, *http.Response, error) {
747747
httpResp, err := http.Get(logURL) //nolint:gosec
748748
if err != nil {
749749
return "", 0, httpResp, fmt.Errorf("failed to download logs: %w", err)
@@ -758,40 +758,56 @@ func downloadLogContent(logURL string, tailLines int) (string, int, *http.Respon
758758
tailLines = 1000
759759
}
760760

761-
const maxMemoryBytes = 5 * 1024 * 1024
762-
var lines []string
761+
const maxLines = 50000
762+
763+
lines := make([]string, maxLines)
763764
totalLines := 0
764-
currentMemoryUsage := 0
765+
writeIndex := 0
765766

766767
scanner := bufio.NewScanner(httpResp.Body)
767768
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
768769

769770
for scanner.Scan() {
770771
line := scanner.Text()
771772
totalLines++
772-
lineSize := len(line) + 1
773773

774-
// Remove lines from the front until we have space for the new line
775-
for currentMemoryUsage+lineSize > maxMemoryBytes && len(lines) > 0 {
776-
removedLineSize := len(lines[0]) + 1
777-
currentMemoryUsage -= removedLineSize
778-
lines = lines[1:]
779-
}
774+
lines[writeIndex] = line
775+
writeIndex = (writeIndex + 1) % maxLines
780776

781-
// Add the new line
782-
lines = append(lines, line)
783-
currentMemoryUsage += lineSize
777+
if totalLines%10000 == 0 {
778+
runtime.GC()
779+
}
784780
}
785781

786782
if err := scanner.Err(); err != nil {
787783
return "", 0, httpResp, fmt.Errorf("failed to read log content: %w", err)
788784
}
789785

790-
if len(lines) > tailLines {
791-
lines = lines[len(lines)-tailLines:]
786+
var result []string
787+
linesInBuffer := totalLines
788+
if linesInBuffer > maxLines {
789+
linesInBuffer = maxLines
792790
}
793791

794-
return strings.Join(lines, "\n"), totalLines, httpResp, nil
792+
startIndex := 0
793+
if totalLines > maxLines {
794+
startIndex = writeIndex
795+
}
796+
797+
for i := 0; i < linesInBuffer; i++ {
798+
idx := (startIndex + i) % maxLines
799+
if lines[idx] != "" {
800+
result = append(result, lines[idx])
801+
}
802+
}
803+
804+
if len(result) > tailLines {
805+
result = result[len(result)-tailLines:]
806+
}
807+
808+
finalResult := strings.Join(result, "\n")
809+
810+
return finalResult, totalLines, httpResp, nil
795811
}
796812

797813
// RerunWorkflowRun creates a tool to re-run an entire workflow run

0 commit comments

Comments
 (0)