tune(logs): 每页条数默认 1000→200,上下文默认 5 条(依据实测数据)

=== 一、每页条数:1000 太多,实测依据 ===
1. 每次查询响应体 671 B/条 → 1000 条 = **655 KB**
2. 前端结果表**没有虚拟滚动**(无 react-window / tanstack virtual),
   1000 行会全部渲染成 DOM 节点 → 滚动卡顿
3. 后端 maxLogQueryLimit 本来就是 1000,我上一版 UI 给了 2000/5000 选项
   是"假选项"(会被静默收敛成 1000),本次去掉
4. 密度参考:cex-ipublic-gateway 每天 3.28 亿条 ≈ **3800 条/秒**,
   1000 条只覆盖 0.26 秒 —— 靠翻页浏览无意义,应靠时间范围/LogQL 收窄

调整:默认 1000 → **200**(后端自身默认值,约 131KB);选项 [100/200/500/1000]
提示文案改为"日志量大时先收窄时间范围或加过滤,比调大每页条数更有效"

=== 二、上下文档数:1 条不够,默认用 5 ===
实测一个 SpringBoot 异常被拆成 **4 条独立日志**:
  16:15:35.259 [reactor-http-epoll-3] ERROR ...AbstractErrorWebExceptionHandler
  org.springframework.web.reactive.resource.NoResourceFoundException: 404 NOT_FOUND
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
    *__checkpoint ⇢ HTTP HEAD "/" [ExceptionHandlingWebHandler]
→ 前后各 1 条(共 2 条)连一个完整异常都拼不出来
→ 前后各 5 条(共 10 条)能看到"异常 + 前后业务日志",是排障的最小可用集
→ 完整 Java 堆栈(20+ 帧)需要 20-50 条

调整:默认 2 → **5**;选项增加 1 → [1/2/5/10/20/50]

镜像:lghost/lokistack:latest + v0.1 = sha256:2bcc86b8e30d
This commit is contained in:
opsx committed 2026-10-28 16:18:48 +00:00
1 parent 3191af8b6a
commit 6364a70215
5 files changed
+12 -7

No files matched your search

@@ -41,7 +41,7 @@ export function LogContextDialog({ context, terms, lines, onLinesChange, onClose
<Select value={String(lines)} onValueChange={value => onLinesChange(Number(value))}>
<SelectTrigger className="h-6 w-16 px-2 text-xs"><SelectValue /></SelectTrigger>
<SelectContent>
{[2, 5, 10, 20, 50].map(value => <SelectItem key={value} value={String(value)}>{value}</SelectItem>)}
{[1, 2, 5, 10, 20, 50].map(value => <SelectItem key={value} value={String(value)}>{value}</SelectItem>)}
</SelectContent>
</Select>
</span>
+6 -4
View File
@@ -68,7 +68,9 @@ export default function LogsPage() {
const [executedRange, setExecutedRange] = useState<{ start: number; end: number } | null>(null)
const [start, setStart] = useState(() => toLocal(new Date(Date.now() - 300000)))
const [end, setEnd] = useState(() => toLocal(new Date()))
const [limit, setLimit] = useState(1000)
// 默认 200:实测 671B/条,200 条约 131KB、DOM 200 行渲染顺畅。
// 后端 maxLogQueryLimit=1000,所以下拉不给 2000/5000(否则静默截断成 1000,是假选项)
const [limit, setLimit] = useState(200)
const [queryHistory, setQueryHistory] = useState(readQueryHistory)
const [entries, setEntries] = useState<LogEntry[]>([])
const [searched, setSearched] = useState(false)
@@ -198,10 +200,10 @@ export default function LogsPage() {
return () => window.clearInterval(timer)
}, [tail, sourceId, query, limit])
/** 上下文前后条数:默认 2 条(原来写死 5),选择后记住,弹窗内可随时改 */
/** 上下文前后条数:默认 5 条(Java 一个异常常拆成 4 条日志,2 条拼不完整),选择后记住 */
const [contextLines, setContextLines] = useState<number>(() => {
const saved = Number(localStorage.getItem('logContextLines'))
return saved > 0 && saved <= 50 ? saved : 2
return saved > 0 && saved <= 50 ? saved : 5
})
/** 记住当前查看上下文的那一行,切换条数时原地重新拉取 */
const [contextRow, setContextRow] = useState<LogEntry | null>(null)
@@ -273,7 +275,7 @@ export default function LogsPage() {
<Select value={String(limit)} onValueChange={value => setLimit(Number(value))}>
<SelectTrigger className="h-9 w-24" aria-label={t('toolbar.limitLabel')}><SelectValue /></SelectTrigger>
<SelectContent>
{[100, 500, 1000, 2000, 5000].map(value => <SelectItem key={value} value={String(value)}>{value}</SelectItem>)}
{[100, 200, 500, 1000].map(value => <SelectItem key={value} value={String(value)}>{value}</SelectItem>)}
</SelectContent>
</Select>
</label>