[{"data":1,"prerenderedAt":166},["ShallowReactive",2],{"work-\u002Fworks\u002Flogstream-cli":3,"work-surround-\u002Fworks\u002Flogstream-cli":157},{"id":4,"title":5,"body":6,"cover":140,"date":141,"demo":142,"description":143,"draft":144,"extension":145,"featured":144,"meta":146,"navigation":147,"path":148,"repo":149,"seo":150,"stack":151,"stem":155,"updated":142,"__hash__":156},"works\u002Fworks\u002Flogstream-cli.md","logstream — 终端日志追踪工具",{"type":7,"value":8,"toc":133},"minimark",[9,22,26,57,60,63,115,118,129],[10,11,12,13,17,18,21],"p",{},"排查线上问题时经常要同时看好几个服务的日志，",[14,15,16],"code",{},"tail -f"," 开一排窗口又乱又难对照时间。",[14,19,20],{},"logstream"," 把多个来源合并成一条按时间排序的统一时间线。",[23,24,25],"h2",{"id":25},"功能",[27,28,29,37,51],"ul",{},[30,31,32,36],"li",{},[33,34,35],"strong",{},"多源合并","：本地文件、stdin、SSH 远端文件可以同时跟随。",[30,38,39,42,43,46,47,50],{},[33,40,41],{},"正则过滤与高亮","：",[14,44,45],{},"--match"," 过滤想看的行，",[14,48,49],{},"--highlight"," 给关键词上色，互不影响。",[30,52,53,56],{},[33,54,55],{},"来源着色","：每个日志源分配固定颜色，扫一眼就知道是哪台机器。",[23,58,59],{"id":59},"实现",[10,61,62],{},"核心是一个最小堆做 k 路归并，每个源一行一行进堆，按时间戳弹出。终端 UI 用 Lip Gloss 处理颜色与宽度截断，Cobra 管命令行参数。",[64,65,70],"pre",{"className":66,"code":67,"language":68,"meta":69,"style":69},"language-bash shiki shiki-themes tokyo-night github-light","logstream follow app.log worker.log --match 'ERROR' --highlight 'timeout'\n","bash","",[14,71,72],{"__ignoreMap":69},[73,74,77,80,84,87,90,94,98,101,104,107,109,112],"span",{"class":75,"line":76},"line",1,[73,78,20],{"class":79},"sirr2",[73,81,83],{"class":82},"snP_1"," follow",[73,85,86],{"class":82}," app.log",[73,88,89],{"class":82}," worker.log",[73,91,93],{"class":92},"sPs86"," --match",[73,95,97],{"class":96},"sbW-k"," '",[73,99,100],{"class":82},"ERROR",[73,102,103],{"class":96},"'",[73,105,106],{"class":92}," --highlight",[73,108,97],{"class":96},[73,110,111],{"class":82},"timeout",[73,113,114],{"class":96},"'\n",[23,116,117],{"id":117},"踩坑记录",[10,119,120,121,124,125,128],{},"goroutine 泄漏是最初版本的最大问题：关闭日志源时没有停掉读取协程。后来用 ",[14,122,123],{},"context.Context"," 统一生命周期，配合 ",[14,126,127],{},"goleak"," 在测试里兜底。",[130,131,132],"style",{},"html pre.shiki code .sirr2, html code.shiki .sirr2{--shiki-default:#C0CAF5;--shiki-light:#6F42C1}html pre.shiki code .snP_1, html code.shiki .snP_1{--shiki-default:#9ECE6A;--shiki-light:#032F62}html pre.shiki code .sPs86, html code.shiki .sPs86{--shiki-default:#E0AF68;--shiki-light:#005CC5}html pre.shiki code .sbW-k, html code.shiki .sbW-k{--shiki-default:#89DDFF;--shiki-light:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":69,"searchDepth":134,"depth":134,"links":135},3,[136,138,139],{"id":25,"depth":137,"text":25},2,{"id":59,"depth":137,"text":59},{"id":117,"depth":137,"text":117},"https:\u002F\u002Fpicsum.photos\u002Fseed\u002Fmoonstream-cli\u002F1600\u002F1000","2025-11-20",null,"一个 Go 写的命令行工具，把多个日志源合并成一条带颜色、可过滤的时间线，支持跟随模式与正则高亮。",false,"md",{},true,"\u002Fworks\u002Flogstream-cli","https:\u002F\u002Fgithub.com",{"title":5,"description":143},[152,153,154],"Go","Cobra","Lip Gloss","works\u002Flogstream-cli","SkjJTmjPJ2ZKBBzQ9Rt6q-8Ub3mIxN85IxQCgbLAZYc",[158,162],{"title":159,"path":160,"stem":161,"children":-1},"Mail Gateway - 企业邮件派发网关","\u002Fworks\u002Fmail-gateway","works\u002Fmail-gateway",{"title":163,"path":164,"stem":165,"children":-1},"Socket Server - Rust 实时通信服务端","\u002Fworks\u002Fsocket-server","works\u002Fsocket-server",1787114431404]