Loki API 完整实战:3 行命令把日志送进去、查出来、管得好
【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki
Loki 是一个"像 Prometheus 一样"的开源日志聚合系统(口号就是Like Prometheus, but for logs)。它的 Loki RESTful 接口做三件事:把日志写得进(push)、查得出(query)、管得好(labels)。日常你可以用 Grafana 或 LogCLI 来消费这些 API,但当你想在自己的采集管道、告警脚本或运维工具里直接和 Loki 打交道时,下面这套 HTTP 端点就是你唯一需要记住的入口。
我们按一条日志的完整旅程来走:先送进去,再查出来,最后学会管理它的"索引"。
1. 把日志送进去:POST 一条日志到 Loki
先搞懂三个基础规范
说白了,Loki API 只有三条约定,懂了就能发请求:
- 基础路径:所有公开端点都挂在
/loki/api/v1/下,本地默认端口3100。 - Content-Type:默认
application/json,高吞吐场景可换application/x-protobuf;支持gzip压缩(用Content-Encoding头声明)。 - 标签(Label)机制:日志不是按内容索引的,而是先按标签分组。标签完全相同的一串日志构成一条"流"(stream)。Loki 把标签集合哈希成 Stream ID,日志条目装进 chunk 压缩存储,另维护一个小索引用于查找——所以标签选得好不好,直接决定查询快不快。
3 行命令把第一条日志推入 Loki
推送端点是POST /loki/api/v1/push,请求体由streams数组组成:每个元素带一份标签stream和若干[纳秒时间戳, 日志内容]的values。
以"支付服务的 webhook 回调"为例,最小可用示例:
curl -X POST http://localhost:3100/loki/api/v1/push \ -H "Content-Type: application/json" \ -d '{ "streams": [ { "stream": {"service": "payment-service", "job": "webhook"}, "values": [ ["'$(date +%s%N)'", "webhook received: order_id=88231, status=pending"], ["'$(date +%s%N)'", "webhook verified: signature OK"] ] } ] }'三个容易踩的坑:
- 时间戳是纳秒,不是毫秒——
date +%s%N正好给出纳秒,用毫秒会被当成 1970 年的日志。 - 同一 stream 内时间戳要单调递增,乱序条目可能被拒绝。
- 一次请求可以塞多个 stream、每个 stream 塞多条日志——批量推送正是 Loki 吞吐高的原因。
推日志的服务端解析逻辑在pkg/loghttp/push/,想看格式细节可以直接读源码;各采集端(Promtail、Alloy、Fluent Bit 等)的接入文档在docs/sources/send-data/。
2. 把日志查出来:围绕"最近一小时的报错"
即时查询:/loki/api/v1/query
先看某一时刻的快照,比如"现在,webhook 里有多少条报错":
curl -G "http://localhost:3100/loki/api/v1/query" \ --data-urlencode 'query={service="payment-service"} |= "error"' \ --data-urlencode "time=$(date +%s"三个参数:query(LogQL 语句)、time(查询时间点,Unix 秒)、limit(返回上限,默认 100)。返回resultType: streams,内容是按流分组的日志条目。
一条 LogQL 看懂范围查询:/loki/api/v1/query_range
真实诉求往往是"看趋势"——过去一小时payment-service每秒报错多少?范围查询就是为此设计的:
curl -G "http://localhost:3100/loki/api/v1/query_range" \ --data-urlencode 'query=sum(rate({service="payment-service"} |= "error" [1m]))' \ --data-urlencode "start=$(date -d '1 hour ago' +%s)" \ --data-urlencode "end=$(date +%s)" \ --data-urlencode "step=15s"| 参数 | 含义 | 大白话 |
|---|---|---|
start/end | 时间窗口 | 看哪一段历史 |
step | 采样步长 | 每 15 秒出一个数据点 |
query | LogQL 语句 | rate(...[1m])把"每分钟条数"平滑成速率 |
响应里resultType变为matrix,数据点按时间排好——拿来画趋势图刚刚好。
顺手一查:这条流有哪些日志源?/loki/api/v1/series
排查多机部署时,先列出匹配某组标签的所有流,等价于"这个服务现在有几台实例在打日志":
curl -G "http://localhost:3100/loki/api/v1/series" \ --data-urlencode 'match[]={service="payment-service"}'完整的 LogQL 语法、指标查询(rate、count_over_time等)写法,仓库里有现成参考:docs/sources/query/_index.md和docs/sources/query/metric_queries.md。
3. 管好日志:把标签当成"索引"来管
回到那张图:标签决定 Stream ID,Stream ID 决定日志存在哪个 chunk。所以"管标签"就是"管索引"——索引设计错了,查得再勤也快不起来。
一行命令列出所有标签名
想知道库里现在有哪些标签维度(service?job?env?):
curl "http://localhost:3100/loki/api/v1/labels"一行命令列出某标签的所有值
/loki/api/v1/label/<name>/values回答"job这个维度上都有什么值"——这是排障时最常用的元数据接口,比如确认job=webhook的日志确实进来了:
curl "http://localhost:3100/loki/api/v1/label/job/values"两个小建议:
- 这两个端点都支持
start/end限定时间范围,别在超大盘上无范围全查。 - 标签值数量(基数)要克制:
instance-id这种上千取值的字段放标签里,索引会先炸;高频变化的字段宁可留在日志正文里用 LogQL 过滤。
4. 上生产前必看:遇到问题怎么办
先对号入座:常见状态码
| 状态码 | 通常意味着 | 排查动作 |
|---|---|---|
| 400 | 请求格式错:JSON 非法、时间戳非纳秒、stream 内乱序 | 打印请求体逐字段核对;确认时间戳是 19 位纳秒 |
| 401 / 403 | 认证/授权失败 | 检查 API 密钥或租户 ID 头是否带对 |
| 429 | 触发限流(写入速率或查询配额) | 降低推送频率/批量大小,或调大服务端 limits 配置 |
| 500 | 服务端内部错误 | 查 Loki 自身日志,多为后端存储抖动 |
排障三连:按这个顺序动手
- 先用标签接口确认数据在不在:
/labels和/label/<name>/values都查得到,说明写入链路是通的,问题出在查询侧(时间范围、LogQL 过滤条件)。 - 再用即时查询缩小范围:去掉 LogQL 过滤只留
{job="webhook"},确认流本身有数据;再逐条加过滤条件,看是哪一步把结果滤没了。 - 最后看响应体里的错误信息:Loki 的 4xx 响应通常带具体原因文本(如"bad timestamp"),比盲目猜配置快得多。
调优三条经验
- 批量推送:单次请求聚合到 100KB~1MB 量级,比每条日志发一次请求的开销低一个数量级。
- 打开压缩:
Content-Encoding: gzip对 JSON 日志压缩比通常能到 5 倍以上。 - 限制返回量:查询始终带
limit(或 LogQL 的| line_format截断),别让一次排障拉回全量流。
5. 下一步
| 想深入 | 去哪里 |
|---|---|
| LogQL 完整语法与示例 | docs/sources/query/_index.md、docs/sources/query/query_examples.md |
| 各采集端接入(Promtail、Fluent Bit 等) | docs/sources/send-data/ |
| 推送请求的解析源码 | pkg/loghttp/push/ |
| 客户端日志条目数据结构 | clients/pkg/logentry/ |
| 命令行查日志 | cmd/logcli/(配合 LogCLI 使用,免开 Grafana) |
从第一条 curl 推到第一条日志查出来,你手里已经有完整的闭环了:push 写入、query 查询、labels 管理。接下来最值得花一小时的事,是把这套调用封装成你自己项目里的一两个函数——到那时你会发现,Loki 的 RESTful 接口真的只需要记五个路径。
【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考