perf: server-side result caching for history aggregation
Cache awk output in /tmp on the remote server, keyed by log path and bucket size. Cache is invalidated only when a new rotated .gz file appears, making repeated loads instant (0.001s vs 4s cold run). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2be12c24cd
commit
fb09f6e028
1 changed files with 20 additions and 1 deletions
|
|
@ -297,13 +297,32 @@ END {
|
||||||
print tot+0, totb+0
|
print tot+0, totb+0
|
||||||
}`
|
}`
|
||||||
|
|
||||||
cmd := fmt.Sprintf(
|
// Cache file is keyed by log path + bucket size (not since, which changes every second).
|
||||||
|
// Cache is valid as long as no new .gz file appeared since it was written.
|
||||||
|
// A log rotation (every ~9 min on high-traffic servers) is the only invalidation event.
|
||||||
|
cacheKey := strings.NewReplacer("/", "_", ".", "_", "-", "_").Replace(base)
|
||||||
|
cachePath := fmt.Sprintf("/tmp/caddyview_%s_%d.cache", cacheKey, bucketSecs)
|
||||||
|
|
||||||
|
findPipe := fmt.Sprintf(
|
||||||
`find %s -name '%s*' -type f -mtime -%d 2>/dev/null | sort -r | `+
|
`find %s -name '%s*' -type f -mtime -%d 2>/dev/null | sort -r | `+
|
||||||
`while read f; do case "$f" in *.gz) zcat "$f" ;; *) cat "$f" ;; esac; done 2>/dev/null | `+
|
`while read f; do case "$f" in *.gz) zcat "$f" ;; *) cat "$f" ;; esac; done 2>/dev/null | `+
|
||||||
`awk -v cutoff=%d -v bucket=%d '%s'`,
|
`awk -v cutoff=%d -v bucket=%d '%s'`,
|
||||||
dir, base, maxAgeDays+1, since, bucketSecs, awkProg,
|
dir, base, maxAgeDays+1, since, bucketSecs, awkProg,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Wrap with server-side cache: hit → instant cat; miss → run awk and tee to cache atomically.
|
||||||
|
cmd := fmt.Sprintf(
|
||||||
|
`CACHE=%s; `+
|
||||||
|
`LATEST=$(find %s -name '%s*.gz' -mtime -%d 2>/dev/null | sort | tail -1); `+
|
||||||
|
`if [ -f "$CACHE" ] && { [ -z "$LATEST" ] || [ "$CACHE" -nt "$LATEST" ]; }; then `+
|
||||||
|
`cat "$CACHE"; `+
|
||||||
|
`else `+
|
||||||
|
`TMPFILE=$(mktemp /tmp/caddyview.XXXXXX 2>/dev/null || echo /tmp/caddyview_fallback.tmp); `+
|
||||||
|
`%s | tee "$TMPFILE" && mv "$TMPFILE" "$CACHE" 2>/dev/null || cat "$TMPFILE" 2>/dev/null; `+
|
||||||
|
`fi`,
|
||||||
|
cachePath, dir, base, maxAgeDays+1, findPipe,
|
||||||
|
)
|
||||||
|
|
||||||
out, err := c.RunCommand(cmd)
|
out, err := c.RunCommand(cmd)
|
||||||
if err != nil && strings.TrimSpace(out) == "" {
|
if err != nil && strings.TrimSpace(out) == "" {
|
||||||
return nil, fmt.Errorf("aggregation failed: %w", err)
|
return nil, fmt.Errorf("aggregation failed: %w", err)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue