Log files: find the history by date, count from the first poll
A file turned on was read from its start to find its last hour: with a Traefik access log that holds months of lines (never rotated by Traefik), LogStream spent minutes on old lines that were all left out, and new lines waited behind them. Entries sent during the first poll were also left out of the count shown in Settings. - start of the FILES_BACKFILL history found by bisection on the dates of the lines; files without dates: only new lines - up to 16 reads of 4 MB per file and per poll - status "behind" (bytes left to read), shown as "Reading the history: N MB left" - the status of a file exists before its first entries are counted Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
194edee6de
commit
1a3b3ee23a
5 files changed
+140
-16
No files matched your search
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -382,3 +383,45 @@ func TestFilesAutoAndErrors(t *testing.T) {
|
||||
t.Fatalf("re-enabled: got %q", msgs(got))
|
||||
}
|
||||
}
|
||||
|
||||
// A large access log: the last hour is found by date, not read from the
|
||||
// start, and every entry is counted from the first poll.
|
||||
func TestFilesBackfillLargeFile(t *testing.T) {
|
||||
dir, data := t.TempDir(), t.TempDir()
|
||||
path := filepath.Join(dir, "access.log")
|
||||
now := time.Now()
|
||||
line := func(at time.Time, n int) string {
|
||||
return fmt.Sprintf(`86.246.223.62 - - [%s] "GET /wp-content/x.png HTTP/2.0" 200 640365 "-" "-" %d "vblog-io-router@file" "http://wordpress" 3ms`+"\n",
|
||||
at.UTC().Format("02/Jan/2006:15:04:05 -0700"), n)
|
||||
}
|
||||
var b strings.Builder
|
||||
const n = 200000 // one line every 3 s for a week: ~32 MB
|
||||
for i := 0; i < n; i++ {
|
||||
b.WriteString(line(now.Add(-time.Duration(n-i)*3*time.Second), i))
|
||||
}
|
||||
appendFile(t, path, b.String())
|
||||
sink := &fileSink{}
|
||||
f := NewFiles(dir, data, time.Hour, sink.add)
|
||||
f.Configure(filesConfig{Sources: []fileSourceDef{{ID: "a1", Name: "traefik-log", Path: path, Enabled: true}}})
|
||||
f.poll(now)
|
||||
if pos := f.st.Pos["a1"]; pos.Off < int64(b.Len())*99/100 {
|
||||
t.Errorf("history read from offset %d of %d", pos.Off, b.Len())
|
||||
}
|
||||
appendFile(t, path, line(now, n))
|
||||
f.poll(now.Add(time.Second))
|
||||
got := sink.take()
|
||||
// The last hour (1200 lines, the oldest one on the edge) and the new line.
|
||||
if len(got) < 1200 || len(got) > 1201 || got[0].App != "traefik-log" || got[len(got)-1].Extra["http_status"] != "200" {
|
||||
t.Fatalf("got %d entries", len(got))
|
||||
}
|
||||
if st := f.Status()["sources"].([]map[string]any)[0]; st["read"] != uint64(len(got)) || st["behind"] != int64(0) || st["detected"] != fmtCLF {
|
||||
t.Errorf("status %+v", st)
|
||||
}
|
||||
// Undated plain text: only new lines.
|
||||
txt := filepath.Join(dir, "app.log")
|
||||
appendFile(t, txt, strings.Repeat("no date here\n", 1000))
|
||||
p := mustParser(t, fmtText, "")
|
||||
if off := backfillStart(txt, p, 13000, now.Add(-time.Hour), now); off != 13000 {
|
||||
t.Errorf("undated: %d", off)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user