Avoid counting all logs for tail reads

This commit is contained in:
LTbinglingfeng
2026-06-15 15:51:15 +08:00
parent db3fdea4a1
commit a47c386319
2 changed files with 21 additions and 68 deletions
+1 -66
View File
@@ -101,12 +101,7 @@ func (h *Handler) GetLogs(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to read log files: %v", errTail)})
return
}
total, errCount := countLogFileLines(files)
if errCount != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to read log files: %v", errCount)})
return
}
writeLogsResponse(c, result.lines, total, result.latest, result.nextCursor, false)
writeLogsResponse(c, result.lines, len(result.lines), result.latest, result.nextCursor, false)
return
}
@@ -612,66 +607,6 @@ func readTailLogLines(path string, limit int) (completeLogRead, error) {
return readCompleteLogLines(path, start, boundary, limit)
}
func countLogFileLines(files []string) (int, error) {
total := 0
for i := range files {
count, errCount := countLogLines(files[i])
if errCount != nil {
if errors.Is(errCount, os.ErrNotExist) {
continue
}
return 0, errCount
}
total += count
}
return total, nil
}
func countLogLines(path string) (int, error) {
file, errOpen := os.Open(path)
if errOpen != nil {
return 0, errOpen
}
defer func() {
_ = file.Close()
}()
info, errStat := file.Stat()
if errStat != nil {
return 0, errStat
}
if info.IsDir() {
return 0, fmt.Errorf("invalid log file")
}
buf := make([]byte, 32*1024)
count := 0
lineLen := 0
for {
n, errRead := file.Read(buf)
for _, b := range buf[:n] {
if b == '\n' {
count++
lineLen = 0
continue
}
lineLen++
if lineLen > logScannerMaxBuffer {
return 0, fmt.Errorf("log line exceeds %d bytes", logScannerMaxBuffer)
}
}
if errRead == io.EOF {
break
}
if errRead != nil {
return 0, errRead
}
}
if lineLen > 0 {
count++
}
return count, nil
}
func tailStartOffset(path string, boundary int64, limit int) (int64, error) {
if limit <= 0 {
return 0, nil
+20 -2
View File
@@ -149,8 +149,8 @@ func TestGetLogsTailLimitReturnsRecentLinesWithCursor(t *testing.T) {
if !reflect.DeepEqual(resp.Lines, wantLines) {
t.Fatalf("lines = %#v, want %#v", resp.Lines, wantLines)
}
if resp.LineCount != 4 {
t.Fatalf("line-count = %d, want full scan count 4", resp.LineCount)
if resp.LineCount != len(wantLines) {
t.Fatalf("line-count = %d, want returned line count %d", resp.LineCount, len(wantLines))
}
if resp.NextCursor == "" {
t.Fatal("next-cursor is empty")
@@ -161,6 +161,24 @@ func TestGetLogsTailLimitReturnsRecentLinesWithCursor(t *testing.T) {
}
}
func TestGetLogsTailLimitDoesNotScanOlderFilesForLineCount(t *testing.T) {
dir := t.TempDir()
rotatedPath := filepath.Join(dir, defaultLogFileName+".1")
if err := os.WriteFile(rotatedPath, []byte(strings.Repeat("x", logScannerMaxBuffer+1)+"\n"), 0o644); err != nil {
t.Fatalf("write rotated log: %v", err)
}
writeMainLog(t, dir, "[2026-06-15 10:00:00] current\n")
resp := performGetLogs(t, newLogsTestHandler(dir, true), "/v0/management/logs?limit=1")
wantLines := []string{"[2026-06-15 10:00:00] current"}
if !reflect.DeepEqual(resp.Lines, wantLines) {
t.Fatalf("lines = %#v, want %#v", resp.Lines, wantLines)
}
if resp.LineCount != len(wantLines) {
t.Fatalf("line-count = %d, want returned line count %d", resp.LineCount, len(wantLines))
}
}
func TestGetLogsNoLimitKeepsFullScanBehavior(t *testing.T) {
dir := t.TempDir()
writeMainLog(t, dir, "complete\npartial")