3 个场景跑通 Loki API:从推送第一条日志到查询错误趋势
【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki
如果你刚接触 Loki,大概率会问两件事:日志怎么写进去?写进去之后怎么查?其实答案就藏在它的 RESTful 接口里。Loki 是一个像 Prometheus 那样为日志设计的开源聚合系统,而 Loki API 就是你和它打交道的全部入口——通过几个/loki/api/v1/开头的端点,你既能完成 Loki 日志推送,也能用 Loki LogQL 查询(LogQL 是 Loki 的日志查询语言,语法和 PromQL 很像)检索数据,还能做 Loki 标签管理,摸清日志流的结构。
动手前,先记住这三件事
在敲第一条 curl 之前,把下面三条约定刻进脑子,后面所有请求都绕不开它们。
- 基础路径:所有端点都挂在
/loki/api/v1/之下,Loki 默认监听 3100 端口,所以本地环境的完整前缀通常是http://localhost:3100/loki/api/v1/。 - 两种数据格式:多数请求接受
application/json,方便人读;写入类接口同时支持application/x-protobuf(Protocol Buffers,一种比 JSON 更紧凑的二进制序列化格式),客户端库在追求吞吐时通常走这条路。 - 三种压缩:请求体可以用
gzip、deflate或snappy压缩,用Content-Encoding头告知 Loki 怎么解开。日志量一大,压缩能省掉一大半带宽。
这三点搞清楚后,就可以进入实战了。
场景一:把日志写进 Loki
📥 这一步在干嘛:往/loki/api/v1/push发一个 POST,把若干条日志按"标签流"批量塞进 Loki。
推送请求的结构很直观:一个streams数组,每个流由两部分组成——stream是这组日志的标签集合(相当于这个流的身份证),values是日志条目数组,每条是[时间戳, 日志内容]。
{ "streams": [ { "stream": { "job": "demo", "host": "server-01" }, "values": [ ["1623456789000000000", "ERROR: Failed to connect to database"], ["1623456790000000000", "WARN: High memory usage detected"] ] } ] }把它变成一条可运行的 curl:
curl -X POST http://localhost:3100/loki/api/v1/push \ -H "Content-Type: application/json" \ -d '{ "streams": [ { "stream": { "job": "demo", "host": "server-01" }, "values": [ ["'"$(date +%s%N)"'", "Hello from Loki API"] ] } ] }'注意一个高频坑:时间戳单位是纳秒。示例里1623456789000000000有 19 位,如果你随手丢进去一个 10 位的秒级时间戳,这条日志要么报错、要么排到时间线的"史前"位置。shell 里date +%s%N正好给出纳秒值。
场景二:把日志查出来
🔍 这一步在干嘛:用 LogQL 从 Loki 里把日志捞出来。Loki 提供两个查询端点,区别在于你要"一个点"还是"一段线"。
| 对比项 | /loki/api/v1/query | /loki/api/v1/query_range |
|---|---|---|
| 回答的问题 | 某个时刻附近发生了什么 | 一段时间内趋势如何变化 |
| 关键参数 | time(查询时间点)、limit(返回条数,默认 100) | start/end/step(范围与步长) |
| 典型用途 | 排查"现在/刚才"的具体报错 | 统计错误量随时间的变化 |
两者都接收query参数放 LogQL 语句,GET 和 POST 均可,URL 里的特殊字符记得做百分号编码({→%7B,"→%22)。
先"查一个点"——拿最近 10 条 api-server 的 error 日志:
curl "http://localhost:3100/loki/api/v1/query?query=%7Bjob%3D%22api-server%22%7D%20%7C~%20%22error%22&limit=10&time=$(date +%s)"再"查一段趋势"——统计过去一小时每分钟 error 的条数:
curl "http://localhost:3100/loki/api/v1/query_range?query=sum(count_over_time(%7Bjob%3D%22api-server%22%7D%20%7C~%20%22error%22%5B1m%5D))&start=$(date -d '1 hour ago' +%s)&end=$(date +%s)&step=60"两者的响应外壳一致:status为success时,data.result里装着结果;流式查询的结果会带上来源流的标签和[时间戳, 内容]列表,方便你确认日志出自哪里。
场景三:看懂标签系统
🏷️ 这一步在干嘛:在写复杂查询之前,先搞清楚自己库里有哪些"抽屉"——标签就是 Loki 的索引结构,作用相当于字典的索引页:先翻标签名(/loki/api/v1/labels),再查某个标签下有哪些值(/loki/api/v1/label/<name>/values),最后带着{job="api-server"}这样的选择器去查日志,检索效率完全不同。
curl http://localhost:3100/loki/api/v1/labels # 返回类似 {"status":"success","data":["job","environment","host"]} curl http://localhost:3100/loki/api/v1/label/job/values # 返回类似 {"status":"success","data":["api-server","frontend","database"]}这也是排查"为什么查不到数据"的第一站:多半是标签名或值写错了。
排错速查
遇到非 2xx 响应,按这张表先自查:
| 状态码 | 含义 | 先检查什么 |
|---|---|---|
| 400 | 请求体格式错误 | JSON 是否合法、时间戳是否纳秒、标签是否合法 |
| 401 | 认证失败 | API Key / Token 是否配置正确 |
| 429 | 触发限流 | 降频或调大 Loki 的限流阈值 |
| 500 | 服务端内部错误 | 翻 Loki 自身日志定位根因 |
提速清单
- 批量推送:一次请求塞满一个批次的流,别一条日志一个请求,单请求控制在 1MB 以内。
- 收敛标签基数:每个流保留 5-10 个标签;把 request_id、用户 ID 这类高基数("取值种类随数据量无限膨胀")信息放日志正文或结构化字段,别塞进标签。
- 开启压缩:推送侧加
gzip,网络开销立降,客户端库默认都会做。 - 非关键日志异步推:对实时性不敏感的数据走异步队列,避免拖慢主流程。
写在最后
回顾一下今天的三件事:/loki/api/v1/push负责写,/loki/api/v1/query与/loki/api/v1/query_range分别负责查一个点和查一段趋势,/loki/api/v1/labels两个端点负责摸清标签索引。想深入细节,看仓库里的官方文档:
- API 与接口示例:docs/sources/query/
- LogQL 查询语言:docs/sources/query/log_queries/
- 日志解析与处理管道(stages):clients/pkg/logentry/
- 推送接口实现:pkg/loghttp/push/
端点就这几个,跑通一遍,Loki 的大门就开着了。
【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考