赛道 A · 任务 A3
日志检索 工具
构建完全基于 SQL 的迷你 Kibana,再用它排查 11:40 开始出现的 checkout 故障。
- 60–120 分钟
- 新手友好
- 任意语言 · CLI 或网页
- 欢迎使用 AI 工具
遇到问题? 可在 #dev 提问,频道位于 Apache Doris Slack。维护者和其他参与者会提供帮助。
准备环境
了解构建目标、Doris 如何简化实现,并启动集群。
构建目标
构建日志检索工具,并用它解决一次故障。
200,000 条日志、六个服务和一个出现故障的上午。在同一张 Doris 表上,使用原生 SQL 实现 BM25 关键词检索,按服务、级别和时间过滤,并实时统计结果。
构建一个小型日志检索工具,包含:
- 一个 搜索框 ,支持关键词、短语和相关性排序;
- 过滤器 ,可选择服务、级别和时间范围;
- 分面计数 ,在结果旁展示各服务、各级别的命中数量;
- 还可提供 时间线 ,按 5 分钟统计错误数。
随后完成真正的排查: 11:40 开始出现 checkout 失败,哪个服务是根因,问题究竟从何时开始? 工具应让答案清晰可见。
草图位于代码面板顶部
Doris 为何适合这个项目
同一张表兼顾搜索与分析。 倒排索引用于关键词查询,相同的
WHERE条件还可用于GROUP BY以统计分面,无需同步第二套系统。真正的相关性排序。
score()通过 BM25 对结果排序,使最相关的日志优先,而非仅按时间新旧排列。低成本过滤。
service和level分别有倒排索引;时间范围则通过排序键裁剪。
代码面板:表定义中的索引语句
开始之前
docker pull apache/doris:all-in-one-4.1.3docker run -d --name doris -p 9030:9030 -p 8030:8030 -p 8040:8040 apache/doris:all-in-one-4.1.3docker exec -it doris mysql -uroot -h127.0.0.1 -P9030curl -LO https://github.com/morningman/demo-env/releases/download/for-hackathon/doris-hackathon-glasgow-2026.zip && unzip doris-hackathon-glasgow-2026.zip && cd doris-hackathon-glasgow-2026
- 主机
- 127.0.0.1
- 端口
- 9030
- 用户
- root无密码
- 数据库
- hackathon
数据
hackathon.app_logs :六个服务共用一张表。
CREATE TABLE app_logs ( ts DATETIME(3) NOT NULL, service VARCHAR(32) NOT NULL, -- api-gateway, auth, catalog, search, checkout, payment level VARCHAR(8) NOT NULL, -- DEBUG / INFO / WARN / ERROR host VARCHAR(32), trace_id VARCHAR(32), status INT, -- HTTP status, when relevant latency_ms INT, message STRING NOT NULL, INDEX idx_msg (message) USING INVERTED PROPERTIES ("parser" = "english", "support_phrase" = "true"), INDEX idx_service (service) USING INVERTED, INDEX idx_level (level) USING INVERTED)DUPLICATE KEY(ts)DISTRIBUTED BY HASH(trace_id) BUCKETS 1PROPERTIES ("replication_num" = "1");seed/a3_app_logs.sql 会生成 2026 年 10 月 13 日的 200,000 条日志 ,仅需一条 INSERT … SELECT … FROM numbers("number" = "200000") ,无需下载。其中包含待排查的故障。
代码面板 → 建表:完整表定义
借助 AI 构建
推荐与 AI 编程助手协作完成任务。 Doris 4.x 的搜索与 AI 能力较新,可能晚于多数模型的训练数据。在让助手编写 SQL 前,请先提供正确上下文:
将下方 上下文提示词 粘贴给编程助手。
让助手阅读本页列出的 参考文档 以及入门包中的
AGENTS.md文件。许多编程助手会自动读取该文件。将 SQL 接入代码前,要求助手先在您的实际集群中运行每条语句。
还可以连接 Doris MCP Server ,参见 任务 A2,让助手自行检查 Schema 和测试查询。
I'm building a log search explorer on Apache Doris 4.1 for a hackathon.Connection: MySQL protocol, 127.0.0.1:9030, user root, empty password, database `hackathon`.Use a plain MySQL driver and raw SQL.Table `app_logs`: ts DATETIME(3), service, level, host, trace_id, status INT, latency_ms INT,message STRING. Inverted indexes on message (english parser, phrase support), service, level.Doris SQL rules:1. Text search: `message MATCH_ANY 'a b'`, `MATCH_ALL`, `MATCH_PHRASE 'a b'`. Never LIKE.2. BM25: `score()` only with a MATCH_* predicate + `ORDER BY score() DESC LIMIT n`, selected plain (`score() AS relevance`): no ROUND() or JOIN in that SELECT. Bind the user's search text as a driver parameter.3. score() cannot be used with GROUP BY. For facet counts run a second query with the same WHERE clause and GROUP BY service, level.4. Time buckets: `minute_floor(ts, 5)`.Build: search box, service/level/time filters, facet counts, and an error timeline.Run every SQL statement against the live cluster first.AI 编程助手容易踩到的 Doris 问题
| Trap | What to do instead |
|---|---|
使用 LIKE '%term%' 进行文本检索 | col MATCH_ANY 'a b' (OR)、 MATCH_ALL (AND)、 MATCH_PHRASE 'a b' ,这些运算符会使用倒排索引 |
在任意查询中调用 score() 函数 | score() 要求在查询中使用 MATCH_* 谓词,放在 WHERE 中,并提供 ORDER BY score() DESC LIMIT n,否则 Doris 会拒绝查询 |
在同一查询中对 score() 进行取整、关联或排名 | 在单表查询中直接保留 score() AS relevance 。如需取整、关联或使用 ROW_NUMBER() ,请在外层查询中操作,并使用子查询,而非 WITH CTE |
score() 位于 GROUP BY 或聚合函数内 | 不支持。统计分面计数时,请复用相同的 WHERE 条件,但去掉 score() |
| 使用 ORM | 建议使用普通 MySQL 驱动和原生 SQL,ORM 可能生成 Doris 不支持的语句 |
开始构建
6 个里程碑, M0 → M5。代码面板会跟随您阅读的步骤。
生成日志
在入门包目录中执行:
M0 · 生成日志bashdocker exec -i doris mysql -uroot -h127.0.0.1 -P9030 < seed/a3_app_logs.sql检查点数秒后应得到: 200,000 条日志,时间从
00:00:00到23:59:59,日期为 10 月 13 日。使用 BM25 进行关键词检索
M1 · 使用 BM25 进行关键词检索sqlUSE hackathon;SELECT ts, service, level, message, score() AS relevanceFROM app_logsWHERE message MATCH_ANY 'timeout refused'ORDER BY relevance DESCLIMIT 20;接入搜索框时,将用户文本作为驱动参数传入(
MATCH_ANY %s);a3/starter.py入门包已提供对应实现。检查点前 20 条结果均为
connection refused日志。BM25 会给稀有词更高权重: refused 出现在 68 条日志中, timeout 出现在 347 条中。单独搜索timeout即可看到其余结果。过滤条件
M2 · 过滤条件sqlSELECT ts, service, level, message, score() AS relevanceFROM app_logsWHERE message MATCH_ANY 'timeout' AND level = 'ERROR' AND service IN ('checkout', 'payment') AND ts >= '2026-10-13 11:00:00' AND ts < '2026-10-13 12:30:00'ORDER BY relevance DESCLIMIT 20;检查点每条结果都是提到 timeout 的 ERROR 日志,只出现两个服务中的一个。
分面计数
score()不能用于聚合,因此分面统计使用相同过滤条件,但不包含它:M3 · 分面计数sqlSELECT service, level, COUNT(*) AS hitsFROM app_logsWHERE message MATCH_ANY 'timeout' AND ts >= '2026-10-13 11:00:00' AND ts < '2026-10-13 12:30:00'GROUP BY service, levelORDER BY hits DESC;检查点该时间窗口中有 163 条匹配日志,全部为
ERROR。计数总和应等于不包含GROUP BY,可使用SELECT COUNT(*)核对,并保持相同的WHERE.错误时间线
M4 · 错误时间线sqlSELECT minute_floor(ts, 5) AS bucket, service, COUNT(*) AS errorsFROM app_logsWHERE level = 'ERROR' AND ts >= '2026-10-13 11:00:00' AND ts < '2026-10-13 12:30:00'GROUP BY bucket, serviceORDER BY bucket, service;检查点两个服务在 11:35 至 12:00 之间出现明显增长;当天其他时间,没有服务在 5 分钟内产生超过 4 条错误。
解决故障
使用工具回答: 哪个服务导致 checkout 失败?具体从哪一分钟开始? 将答案及其验证查询写入 README。
完成并提交
完成清单,展示成果,领取徽章。
完成标准
您的检查清单提交并领取徽章
参与 → 提交 → 领取徽章。
请将成果放到以 您的 GitHub ID命名的目录中:包括代码和 README,说明项目功能、运行方式、使用的 Doris 能力,并附一张截图或 GIF。
提交 Pull Request ,将成果添加到 morningman/demo-env ,目录为
doris-hackathon-glasgow-2026/<your-github-id>/。可以先 Fork 后推送,或使用 GitHub 的 Add file → Upload files(添加文件 → 上传文件)。无需填写其他内容。分享成果 到
#dev( Apache Doris Slack):附上 Pull Request 或仓库链接,以及截图或简短演示。问题交流、成果提交和徽章领取都在该频道处理。
每位参与任务的开发者都可获得 Apache Doris 贡献者徽章,无需先有 PR 合入 Doris。任务没有截止日期,可按自己的节奏完成。可以组队,也可独立参与;请将每位成员的 GitHub ID 写入 README.
进阶目标
短语检索与输入补全:
MATCH_PHRASE 'connection refused',MATCH_PHRASE_PREFIX实现边输入边搜索。链路视图:点击一条日志,按时间顺序展示具有相同
trace_id的全部日志。查询字符串检索:尝试
SEARCH()DSL,使用 Lucene 风格的field:term AND …,参阅 SEARCH 函数.实时日志尾部视图:每秒插入少量新行,并自动刷新。
索引与无索引对比:比较
MATCH_ANY与LIKE '%timeout%'在完整表上的耗时,并展示结果。
故障排查与参考资料
| Symptom | Fix |
|---|---|
docker: command not found 出现在 macOS 上 | 启动 Docker Desktop;若已运行,请为 CLI 创建链接: sudo ln -s /Applications/Docker.app/Contents/Resources/bin/docker /usr/local/bin/docker |
error getting credentials 出现在拉取镜像时 | 请移除 credsStore 字段,所在文件为 ~/.docker/config.json (仅适用于本地开发) |
port is already allocated | 9030、8030 或 8040 已被其他程序占用,常见原因是另一个 Doris 实例。先查看运行中的容器(docker ps),再停止冲突的服务;也可映射其他主机端口,例如 -p 19030:9030,然后连接 19030 |
The container name "/doris" is already in use | 此前已启动过该容器,可执行: docker start doris。如需从头开始,请执行 docker rm -f doris ,此操作会删除容器数据 |
容器退出,或始终未变为 (healthy) | 请查看 docker logs doris。通常是内存不足,请在 Docker Desktop 的 Settings → Resources 中分配至少 6 GB。Apple Silicon 设备不要添加 --platform linux/amd64 |
permission denied: ./doris.sh | 解压工具可能丢失了可执行权限,请执行: chmod +x doris.sh,或运行 bash doris.sh start |
Current database is not set | 请先执行 USE hackathon; ,或在连接时使用 -Dhackathon |
score() function requires WHERE clause with MATCH function, ORDER BY and LIMIT | 请添加 MATCH_* 谓词、 ORDER BY score() DESC 以及 LIMIT,并保持 score() 不被其他表达式包裹,参见前文说明 |
| 超过 10 分钟仍未解决 | 可在 #dev 频道提问,位于 Apache Doris Slack |
参考资料
Apache Doris 黑客松
