关于 logql-generator
logql-generator 是用于 Loki 日志的交互式 LogQL 查询生成技能,适合查询、仪表板、告警和故障排查。它按阶段收集需求与版本信息,再生成兼顾兼容性的查询。
主要功能
- 01引导收集查询目标和日志详情
- 02根据 Loki 与 Grafana 版本调整语法
- 03支持查询规划及最终或分步输出
- 04复杂查询执行参考资料检查
- 05提供运行指引与兼容性说明
适用场景
- 01为服务创建 Loki 错误率查询
- 02构建 LogQL 告警表达式
- 03将排障目标转换为日志查询
- 04根据 Loki 日志生成仪表板指标
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ akin-ozer/ cc-devops-skills --skill logql-generator安装后在 Claude Code 中输入/logql-generator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/common_queries.logqlreferences/best_practices.mdscripts/run_regression_checks.shtests/test_loki_runtime_integration.pytest_skill_contract.py详细介绍
LogQL 查询生成器
概述
用于生成可投入生产的 LogQL 查询的交互式工作流。LogQL 是 Grafana Loki 的查询语言,支持索引标签选择、日志行筛选、解析和指标聚合。
触发提示
- “编写一个按服务统计错误率的 LogQL 查询。”
- “帮我构建一个 Loki 告警查询。”
- “把这项故障排查需求转换成 LogQL。”
- “我需要逐步构建 LogQL 查询。”
使用此技能通过 Loki 日志生成查询、仪表板查询和告警表达式,以及进行故障排查。
执行流程(确定性)
始终按顺序执行各阶段。不要跳过必需阶段。
阶段 1(必需):收集意图
使用 AskUserQuestion 收集目标和使用场景。
模板:
- “你的主要目标是什么:调试、告警、仪表板指标,还是调查?”
- “你需要日志查询(原始日志行)还是指标查询(数值输出)?”
- “需要覆盖多长的时间范围(例如,过去 15m、1h、24h)?”
如果 AskUserQuestion 不可用,则:
- 用纯文本提出相同问题,然后继续。
阶段 2(必需):收集日志来源详情
收集:
- 流选择器的标签(
job、namespace、app、service_name、cluster) - 日志格式(JSON、logfmt、纯文本、混合格式)
- 已知的筛选/聚合字段(
status、level、duration、path、trace_id)
处理信息模糊或回答不完整的情况:
- 如果缺少必需字段,提出一个有针对性的追问。
- 如果仍未获取信息,则基于明确假设继续。
- 在输出中以
Assumptions:为假设添加前缀,方便用户快速更正。
阶段 3(必需):确认 Loki 和 Grafana 版本
收集或推断:
- Loki 版本(例如,
2.9.x、3.0+、未知) - Grafana 版本(例如,
10.x、11.x、未知) - 部署环境(可自托管的 Loki、Grafana Cloud、未知)
版本兼容性策略:
- 如果版本已知,仅使用最新的兼容语法。
- 如果版本未知,优先采用兼容性最高的语法,默认避免仅适用于 3.x 的功能。
- 如果版本未知,另外提供可选的“3.x 优化版本”。
默认避免使用以下功能(版本未知时):
- 模式匹配运算符
|>和!> approx_topk- 特定于结构化元数据的行为(
detected_level、对加速元数据筛选的假设)
阶段 4(必需):确认计划和输出模式
用通俗语言展示计划,然后请用户选择输出模式。
计划模板:
LogQL Query Plan
Goal: <goal>
Query type: <log or metric>
Streams: <selector>
Filters/parsing: <filters + parser>
Aggregation window: <function and [range]>
Compatibility mode: <version-aware or compatibility-first>
模式选择模板:
- “你想要
final query only(默认),还是incremental build(逐步构建)?”
如果用户未选择,默认使用 final query only。
阶段 5(有条件,阻塞):复杂查询的参考检查点
以下情况视为复杂查询:
- 嵌套聚合(
topk(sum by(...))、多个sum by、百分位数) - 对性能敏感的查询(高流量日志流、长时间范围)
- 告警表达式
- 模板函数(
line_format、label_format) - 大量使用正则表达式进行提取、IP 匹配、模式解析
- 使用 Loki 3.x 功能
阻塞检查点规则:
- 生成查询前,通过明确的文件打开/读取操作读取相关文件。
- 最少读取以下文件:
examples/common_queries.logql,用于检查语法和查询模式references/best_practices.md,用于了解性能和告警指导
- 完成此检查点前,不得生成最终查询。
文件读取工具不可用时的回退方案:
- 说明在此环境中无法读取参考文件。
- 生成保守查询(优先兼容性,使用较简单的运算符)。
- 将结果标记为
Unverified against local references。
第 6 阶段(条件):外部文档查询策略(先查 Context7,再查 WebSearch)
仅在需要了解特定版本的行为、语法不明确,或本地参考资料未涵盖的高级功能时,才进行外部查询。
查询顺序:
- 优先使用 Context7:
- 使用
mcp__context7__resolve-library-id,并设置libraryName="grafana loki" - 使用
mcp__context7__query-docs查询具体主题
- 使用
- 其次使用 WebSearch(仅作回退),适用于以下情况:
- Context7 不可用
- Context7 未提供所需的特定版本详情
- 需要确认最新版本或弃用情况
WebSearch 回退限制:
- 优先查阅 Grafana/Loki 官方文档和发行说明。
- 标明哪些说法来自回退搜索。
第 7 阶段(必需):生成查询
第 7A 阶段(默认):仅返回最终查询
返回一条可用于生产环境的查询,并附简短说明。
第 7B 阶段(可选):增量构建模式
在用户要求时,或调试复杂流水线时使用。
分步模板:
- 流选择器
- 行过滤器
- 解析器
- 解析字段过滤器
- 聚合/时间窗口
第 8 阶段(必需):提供用法和检查项
始终包括:
- 最终查询或增量查询序列
- 如何运行(Grafana Explore/面板或
logcli) - 可调参数(标签、阈值、范围)
- 任何假设和兼容性说明
AskUserQuestion 模板
信息收集模板
- “要针对哪个系统/服务生成此查询?”
- “哪些标签可用于可靠地选择流?”
- “如何定义匹配项(错误文本、状态码、延迟阈值、用户路径)?”
- “输出应为原始日志,还是用于告警/仪表板的指标?”
版本模板
- “你运行的是哪个 Loki 版本?”
- “你使用的是哪个 Grafana 版本?”
- “如果不清楚,我是否应生成兼容性优先的查询,并附上可选的 3.x 变体?”
歧义追问模板
- “我缺少
<field>。是否可以假设为<default>,以便继续?”
核心模式
流选择与过滤
{job="app"} |= "error" |= "timeout"
{job="app"} |~ "error|fatal|critical"
{job="app"} != "debug"
解析
{app="api"} | json | level="error" | status_code >= 500
{app="api"} | logfmt | caller="database.go"
{job="nginx"} | pattern "<ip> - - [<_>] \"<method> <path>\" <status> <size>"
指标聚合
rate({job="app"} | json | level="error" [5m])
sum by (app) (count_over_time({namespace="prod"} | json [5m]))
sum(rate({app="api"} | json | level="error" [5m])) / sum(rate({app="api"}[5m])) * 100
quantile_over_time(0.95, {app="api"} | json | unwrap duration [5m])
topk(10, sum by (error_type) (count_over_time({job="app"} | json | level="error" [1h])))
格式化与 IP 匹配
{job="app"} | json | line_format "{{.level}}: {{.message}}"
{job="app"} | json | label_format env=`{{.environment}}`
{job="nginx"} | logfmt | remote_addr = ip("192.168.4.0/24")
查询构建规则
- 使用具体的流选择器(优先使用索引标签)。
- 优先采用以下过滤顺序:行过滤 -> 解析 -> 解析字段过滤。
- 优先采用以下解析器成本顺序:
pattern>logfmt>json>regexp。 - 如果 Loki 版本未知,请使用兼容性优先的语法。
- 对于复杂/关键查询,在最终输出前完成第 5 阶段检查点。
高级技巧
多个解析器
{app="api"} | json | regexp "user_(?P<user_id>\\d+)"
使用 Unwrap 获取数值指标
sum(sum_over_time({app="api"} | json | unwrap duration [5m]))
模式匹配运算符(Loki 3.0+,比正则表达式快 10 倍)
{service_name=`app`} |> "<_> level=debug <_>"
逻辑运算符
{app="api"} | json | (status_code >= 400 and status_code < 500) or level="error"
Offset 修饰符
sum(rate({app="api"} | json | level="error" [5m])) - sum(rate({app="api"} | json | level="error" [5m] offset 1d))
标签操作
{app="api"} | json | keep namespace, pod, level
{app="api"} | json | drop pod, instance
注意:LogQL 没有
dedup或distinct运算符。请使用sum by (field)等指标聚合来以编程方式去重。
Loki 3.x 主要功能
结构化元数据
无需索引的高基数数据(trace_id、user_id、request_id):
# Filter AFTER stream selector, NOT in it
{app="api"} | trace_id="abc123" | json | level="error"
查询加速(Bloom 过滤器)
在解析器之前放置结构化元数据过滤器:
# ACCELERATED
{cluster="prod"} | detected_level="error" | logfmt | json
# NOT ACCELERATED
{cluster="prod"} | logfmt | json | detected_level="error"
approx_topk(概率性)
approx_topk(10, sum by (endpoint) (rate({app="api"}[5m])))
用于告警的 vector()
sum(count_over_time({app="api"} | json | level="error" [5m])) or vector(0)
自动标签
- service_name:根据容器名称自动填充
- detected_level:当
discover_log_levels: true时自动检测(存储为结构化元数据)
函数参考
日志范围聚合
| 函数 | 描述 |
|---|---|
rate(log-range) | 每秒条目数 |
count_over_time(log-range) | 条目数 |
bytes_rate(log-range) | 每秒字节数 |
bytes_over_time(log-range) | 时间范围内的总字节数 |
absent_over_time(log-range) | 无日志时返回 1 |
规则:
- 对于原始日志字节量,请使用
bytes_over_time(<log-range>)。 - 对于从日志内容中提取的数值字节字段,请使用
| unwrap bytes(field)和解包后的范围聚合函数。
未展开范围聚合
| 函数 | 描述 |
|---|---|
sum_over_time、avg_over_time、max_over_time、min_over_time | 聚合数值 |
quantile_over_time(φ, range) | φ 分位数(0 ≤ φ ≤ 1) |
first_over_time、last_over_time | 区间内的第一个/最后一个值 |
stddev_over_time | 未展开值的总体标准差 |
stdvar_over_time | 未展开值的总体方差 |
rate_counter | 将值视为单调递增计数器,计算每秒速率 |
聚合运算符
sum、avg、min、max、count、stddev、topk、bottomk、approx_topk、sort、sort_desc
分组方式:sum by (label1, label2) 或 sum without (label1)
转换函数
| 函数 | 描述 |
|---|---|
duration_seconds(label) | 转换时长字符串 |
bytes(label) | 转换字节字符串(KB、MB) |
label_replace()
label_replace(rate({job="api"} |= "err" [1m]), "foo", "$1", "service", "(.*):.*")
解析器参考
logfmt
| logfmt [--strict] [--keep-empty]
--strict:遇到格式错误的条目时返回错误--keep-empty:保留独立键
JSON
| json # All fields
| json method="request.method", status="response.status" # Specific fields
| json servers[0], headers="request.headers[\"User-Agent\"]" # Nested/array
pattern
| pattern "<ip> - - [<timestamp>] \"<method> <path> <_>\" <status> <size>"
命名占位符会成为提取出的标签;<_> 会丢弃字段。
regexp
| regexp "(?P<level>\\w+): (?P<message>.+)"
使用命名捕获组(?P<name>)。速度比 pattern/logfmt/json 慢。
decolorize
| decolorize
移除 ANSI 颜色转义码。当日志来自终端输出时,请在解析前应用此解析器。
unpack
| unpack
解包由 Promtail 的 pack 管道阶段打包的日志条目。还原原始日志行及其中嵌入的标签。
模板函数
line_format 和 label_format 常用函数:
字符串:trim、upper、lower、replace、trunc、substr、printf、contains、hasPrefix
数学:add、sub、mul、div、addf、subf、floor、ceil、round
日期:date、now、unixEpoch、toDate、duration_seconds
正则表达式:regexReplaceAll、count
其他:fromJson、default、int、float64、__line__、__timestamp__
详细用法请参阅 examples/common_queries.logql。
告警规则
# Alert when error rate exceeds 5%
(sum(rate({app="api"} | json | level="error" [5m])) / sum(rate({app="api"}[5m]))) > 0.05
# With vector() to avoid "no data"
sum(rate({app="api"} | json | level="error" [5m])) or vector(0) > 10
错误处理
| 问题 | 解决方案 |
|---|---|
| 没有结果 | 检查标签是否存在,确认时间范围,并单独测试流选择器 |
| 查询缓慢 | 使用具体的选择器,在解析前进行筛选,并缩短时间范围 |
| 解析错误 | 确认日志格式与解析器匹配,测试 JSON 是否有效 |
| 高基数 | 对唯一值使用行筛选器而非标签筛选器,并进行聚合 |
文档查询
使用第 6 阶段策略。遇到以下情况时查询外部文档:
| 触发条件 | 要搜索的主题 | 使用的工具 |
|---|---|---|
| 用户提及 Loki 3.x 功能 | structured metadata、bloom filters、detected_level | 优先使用 Context7 |
需要 approx_topk 函数 | approx_topk probabilistic | 优先使用 Context7 |
模式匹配运算符(|>、!>) | pattern match operator | 优先使用 Context7 |
用于告警的 vector() 函数 | vector function alerting | 优先使用 Context7 |
| 记录规则配置 | recording rules loki | 优先使用 Context7 |
| 语法或边界情况不明确 | 具体函数/运算符 | 优先使用 Context7 |
| 询问特定版本的行为 | 版本 + 功能 | 备用方案:WebSearch |
| Grafana Alloy 集成 | grafana alloy loki | 备用方案:WebSearch |
资源
examples/common_queries.logql:查询模式、模板函数示例references/best_practices.md:优化、反模式、告警指南
示例流程
示例 A:仅输出最终查询(默认)
- 用户请求按服务统计过去 15 分钟的 5xx 速率。
- 捕获标签并设置格式(
json)。 - 确认版本和模式(
final query only)。 - 生成一个查询:
sum by (service) (rate({namespace="prod", app="api"} | json | status_code >= 500 [15m]))
示例 B:增量构建(可选)
- 用户请求排查登录失败问题,并要求逐步模式。
- 提供分阶段构建:
{app="auth"}
{app="auth"} |= "login failed"
{app="auth"} |= "login failed" | json
sum(count_over_time({app="auth"} |= "login failed" | json [5m]))
- 说明如果任何步骤返回零结果,应在哪里停止。
完成标准
仅当所有检查均通过时,才将任务标记为完成:
- 已完成所需阶段(1、2、3、4、7、8)。
- 对于任何复杂查询,已完成阶段 5 检查点。
- 需要查阅外部文档时,已按顺序先使用 Context7,再使用 WebSearch。
- 已明确选择输出模式或采用默认模式(
final query only)。 - 版本未知时,已说明 Loki/Grafana 兼容性假设。
- 最终输出包含查询文本、使用说明、可调参数和假设。
版本说明
- Loki 3.0+:布隆过滤器、结构化元数据、模式匹配运算符(
|>、!>) - Loki 3.3+:
approx_topk函数 - Loki 3.5+:Promtail 已弃用(请使用 Grafana Alloy)
- Loki 3.6+:可水平扩展的压缩器,Loki UI 作为 Grafana 插件
弃用项:Promtail(请使用 Alloy)、BoltDB 存储(请使用带有 v13 架构的 TSDB)