Решение: truncate по умолчанию, delete опционально, лимиты tail и max 512 MiB на sync cleanup. Co-authored-by: Cursor <[email protected]>
4.4 KiB
Creative: Runtime Logs Cleanup & Tail (CP-3)
📌 CREATIVE PHASE START: Cleanup Semantics & Tail Limits ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1️⃣ PROBLEM
Description: Sync cleanup больших .log файлов на HTTP worker; tail/preview без OOM. Нужны чёткие лимиты и режимы очистки, совместимые с sidecar docker logs -f >> file (файл пересоздаётся при рестарте sidecar).
Requirements:
- Cleanup — синхронный HTTP (решение заказчика)
- Audit:
size_before,size_after,action - Sidecar продолжает писать в тот же путь после truncate
- Защита от чтения гигабайтных файлов в tail
Constraints:
- Без
jobs.Registryдля cleanup - Request timeout: разумный предел на handler (context с deadline 60s для cleanup)
- Файлы: только allowlisted basenames (CP-4)
2️⃣ OPTIONS — Cleanup mode
| Option | Описание |
|---|---|
| A | Truncate по умолчанию (os.Truncate(0) или O_TRUNC) — файл остаётся, inode может сохраниться |
| B | Delete по умолчанию — os.Remove, sidecar создаст при следующей записи |
| C | Rotate: rename to .old + create new |
| D | Truncate только < N MB, иначе reject |
3️⃣ ANALYSIS — Cleanup
| Criterion | A Truncate | B Delete | C Rotate | D Size gate |
|---|---|---|---|---|
| Sidecar совместимость | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
| Predictable filename | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| Sync latency | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| Audit clarity | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
Key insight: sidecar открывает файл через shell redirect >>; truncate обнуляет содержимое без смены имени в list — оператор видит тот же evobgp-all.log. Delete допустим как явная опция (файл исчезнет из list до следующей строки sidecar).
4️⃣ DECISION — Cleanup
Default: mode=truncate (query param, default when omitted).
Optional: mode=delete — только operator, UI second action «Удалить файл полностью».
Max file size for cleanup: 512 MiB — выше reject 413 / problem file_too_large (защита sync worker). Документировать в OpenAPI.
Handler timeout: 60s context на cleanup; для типичных log < 512 MiB truncate/delete — миллисекунды.
Audit: всегда запись после успешной операции; при ошибке — no audit, 500.
2️⃣ OPTIONS — Tail / preview
| Option | Lines default | Bytes cap |
|---|---|---|
| T1 | 200 lines | 256 KiB |
| T2 | 500 lines | 1 MiB |
| T3 | 1000 lines | 512 KiB |
4️⃣ DECISION — Tail
Query params GET /v1/runtime-logs/files/{filename}:
| Param | Default | Max | Note |
|---|---|---|---|
lines |
200 | 2000 | Читать с конца файла |
bytes |
— | 262144 (256 KiB) | Альтернатива lines; если оба — min лимит |
grep |
— | max 128 chars | Опционально; фильтр после чтения tail chunk |
Implementation: read last N bytes (cap 256 KiB), split lines, take last lines (cap 2000). Не mmap всего файла.
grep: простой strings.Contains post-filter (не regex) — снижает ReDoS risk.
5️⃣ IMPLEMENTATION NOTES
internal/runtimelogs/tail.go—TailFile(path, opts) ([]byte, truncated bool, err)internal/runtimelogs/cleanup.go—Cleanup(path, mode) (sizeBefore, sizeAfter int64, err)- OpenAPI enum
RuntimeLogCleanupMode: truncate | delete - Response cleanup:
{ "audit_id", "filename", "action", "size_before", "size_after" } - UI: primary button «Очистить (обнулить)»; secondary «Удалить файл»
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📌 CREATIVE PHASE END: Cleanup & Tail