LogQL查询生成器
概览
交互式工作流,用于生成生产就绪的LogQL查询。LogQL是Grafana Loki的查询语言——分布式grep,带有用于过滤的标签,以及聚合和度量功能。
何时使用此技能
- 创建用于日志分析、仪表板或告警的LogQL查询
- 将日志分析需求转换为LogQL表达式
- 通过日志分析进行故障排查
- 处理结构化日志(JSON,logfmt)
交互式查询规划工作流
关键:在生成查询之前,始终与用户进行协作规划。
第1阶段:了解目标
使用AskUserQuestion收集需求:
- 主要目标:错误分析、性能跟踪、安全监控、调试、模式检测?
- 用例:仪表板、告警规则、临时故障排除、度量生成?
- 上下文:应用程序/服务、环境、时间范围、日志格式?
第2阶段:确定日志源
- 标签:哪些标签标识您的日志?(
job、namespace、app、level、service_name) - 日志格式:JSON、logfmt、纯文本或自定义?
- 策略:使用标签进行流选择(索引),行过滤器用于内容(未索引)
第3阶段:确定查询参数
- 查询类型:日志查询(返回行)或度量查询(计算值)?
- 过滤:流选择器
{job="app"},行过滤器|= "error",标签过滤器| status >= 500 - 解析:
| json,| logfmt,| pattern "<ip> - <user>",| regexp "(?P<field>...)" - 聚合:
count_over_time(),rate(),sum by (label),quantile_over_time() - 时间范围:
[5m],[1h],[24h]
第4阶段:提出计划并确认
在生成代码之前,用简单的英语呈现计划:
## LogQL查询计划
**目标**:[描述]
**查询结构**:
1. 选择流:`{label="value"}`
2. 过滤行:[操作]
3. 解析日志:[解析器]
4. 聚合:[函数]
**这是否符合您的意图?**
使用AskUserQuestion确认后再进行。
第4a阶段:咨询参考文件(复杂查询必需)
强制性:在技能执行期间明确使用Read工具阅读参考文件。不要依赖先前的知识或缓存信息。
在生成查询之前,当查询涉及以下任何内容时,您必须使用Read工具:
| 查询复杂性 | 所需操作 |
|---|---|
| 复杂聚合(嵌套topk,多个sum by,百分位数) | Read examples/common_queries.logql获取验证过的模式 |
| 性能关键查询(大时间范围,高流量流) | Read references/best_practices.md第1-5节,第15-18节 |
| 告警规则 | Read references/best_practices.md第19-21节,第39节 |
| 结构化元数据/Loki 3.x功能 | Read references/best_practices.md第35-37节 |
| 模板函数(line_format,label_format) | Read examples/common_queries.logql模板函数部分 |
| IP过滤,模式提取,正则表达式 | Read examples/common_queries.logql获取确切语法 |
如何咨询(必须使用Read工具):
# 在技能执行期间使用这些路径调用Read工具:
Read(".claude/skills/logql-generator/examples/common_queries.logql") # 用于查询模式
Read(".claude/skills/logql-generator/references/best_practices.md") # 用于优化和反模式
示例工作流:
- 用户请求带有topk聚合的告警规则
- 必须调用:
Read examples/common_queries.logql获取topk模式 - 必须调用:
Read references/best_practices.md获取告警最佳实践(第19-21节,第39节) - 然后使用您刚刚阅读的文件中的模式生成查询
为什么这很重要:参考文件包含未经测试的模式和未涵盖的边缘情况。在每次技能执行期间显式咨询,确保您使用最新的模式并防止语法错误。
第5阶段:生成查询
最佳实践
- 特定流选择器:
{namespace="prod", app="api", level="error"}而不是{namespace="prod"} - 过滤器顺序:行过滤器 → 解析 → 标签过滤器(从快到慢)
- 解析器性能:pattern > logfmt > json > regexp
核心查询模式
日志过滤:
{job="app"} |= "error" |= "timeout" # 包含两者
{job="app"} |~ "error|fatal|critical" # 正则匹配
{job="app"} != "debug" # 排除
JSON/logfmt解析:
{app="api"} | json | level="error" | status_code >= 500
{app="app"} | 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])
# Top N
topk(10, sum by (error_type) (count_over_time({job="app"} | json | level="error" [1h])))
格式化:
{job="app"} | json | line_format "{{.level}}: {{.message}}"
{job="app"} | json | label_format env="{{.environment}}"
IP过滤(解析后首选标签过滤器以提高精度):
{job="nginx"} | logfmt | remote_addr = ip("192.168.4.0/24")
第5a阶段:增量查询构建(教育/调试)
何时使用此阶段:
- 用户正在学习LogQL
- 复杂的多阶段查询
- 调试查询问题
- 用户明确要求逐步解释
逐步呈现查询构建:
## 逐步构建您的查询
### 第1步:流选择器(验证日志存在)
```logql
{app="api"}
首先测试这个以确认日志正在流动
第2步:添加行过滤器(快速预过滤)
{app="api"} |= "error"
在解析之前减少数据
第3步:添加解析器(提取字段)
{app="api"} |= "error" | json
现在您可以在提取的标签上进行过滤
第4步:添加标签过滤器(精确过滤)
{app="api"} |= "error" | json | level="error"
对解析后的数据进行最终过滤
第5步:添加聚合(如果是度量查询)
sum(count_over_time({app="api"} |= "error" | json | level="error" [5m]))
完整的度量查询
**增量构建的好处:**
1. 确定哪个步骤失败(无结果,解析错误)
2. 了解每个操作的性能影响
3. 通过测试每个阶段来调试意外结果
4. 自然地学习LogQL查询结构
**使用AskUserQuestion提供增量模式:**
- 选项:"显示逐步构建"与"仅显示最终查询"
### 第6阶段:提供使用说明
1. **最终查询**及解释
2. **如何使用**:Grafana面板,Loki告警规则,`logcli query`,HTTP API
3. **自定义**:要修改的标签,要调整的阈值
## 高级技术
### 多个解析器
```logql
{app="api"} | json | regexp "user_(?P<user_id>\\d+)"
解析数值度量
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):
# 在流选择器之后过滤,而不是在其中
{app="api"} | trace_id="abc123" | json | level="error"
查询加速(布隆过滤器)
将结构化元数据过滤器放置在解析器之前:
# 加速
{cluster="prod"} | detected_level="error" | logfmt | json
# 未加速
{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) |
每秒字节数 |
absent_over_time(log-range) |
如果没有日志则返回1 |
解析范围聚合
| 函数 | 描述 |
|---|---|
sum_over_time, avg_over_time, max_over_time, min_over_time |
聚合数值 |
quantile_over_time(φ, range) |
φ-分位数(0 ≤ φ ≤ 1) |
first_over_time, last_over_time |
第一个/最后一个值 |
聚合操作符
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 # 所有字段
| json method="request.method", status="response.status" # 特定字段
| json servers[0], headers="request.headers[\"User-Agent\"]" # 嵌套/数组
模板函数
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了解详细用法。
告警规则
# 当错误率超过5%时发出告警
(sum(rate({app="api"} | json | level="error" [5m])) / sum(rate({app="api"}[5m]))) > 0.05
# 使用vector()避免"无数据"
sum(rate({app="api"} | json | level="error" [5m])) or vector(0) > 10
错误处理
| 问题 | 解决方案 |
|---|---|
| 无结果 | 检查标签是否存在,验证时间范围,单独测试流选择器 |
| 查询慢 | 使用特定选择器,解析前过滤,减少时间范围 |
| 解析错误 | 验证日志格式是否与解析器匹配,测试JSON有效性 |
| 高基数 | 使用行过滤器而不是标签过滤器进行唯一值过滤,聚合 |
文档查找
何时获取外部文档(必需)
触发上下文7 MCP或WebSearch时,查询涉及以下任何内容:
| 触发器 | 主题搜索 | 使用工具 |
|---|---|---|
| 用户提到"Loki 3.x"功能 | structured metadata, bloom filters, detected_level |
context7 MCP |
需要approx_topk函数 |
approx_topk probabilistic |
context7 MCP |
模式匹配操作符(|>, !>) |
pattern match operator |
context7 MCP |
vector()函数用于告警 |
vector function alerting |
context7 MCP |
| 记录规则配置 | recording rules loki |
context7 MCP |
| 不清楚的语法或边缘情况 | 特定功能或操作符 | context7 MCP |
| 版本特定行为问题 | 版本+功能 | WebSearch |
| Grafana Alloy集成 | grafana alloy loki |
WebSearch |
如何使用
context7 MCP(首选 - 权威文档):
1. mcp__context7__resolve-library-id with libraryName="grafana loki"
2. mcp__context7__get-library-docs with context7CompatibleLibraryID and topic="[specific topic]"
WebSearch(最新功能备用):
WebSearch查询:"Grafana Loki LogQL [主题]文档[年份]"
示例工作流
当用户询问"在Loki 3.x中进行错误跟踪与跟踪相关性":
- 识别触发器:“Loki 3.x” + “trace” → 结构化元数据
- 获取文档:
mcp__context7__get-library-docs主题为"structured metadata trace_id" - 应用文档中的模式以生成准确的查询
资源
- examples/common_queries.logql:全面的查询示例
- references/best_practices.md:39+ LogQL最佳实践,性能优化,反模式
指南
- 始终交互式规划 - 在生成之前呈现简单的英语计划
- 使用AskUserQuestion - 收集需求并确认计划
- 必须使用Read工具进行复杂查询 - 在技能执行期间显式调用
Read对examples/common_queries.logql和references/best_practices.md进行告警规则、topk、百分位数或性能关键查询。不要跳过这一步或依赖先前的知识。 - 获取高级功能文档 - 当涉及Loki 3.x功能、approx_topk或不清楚的语法时使用context7 MCP(见文档查找触发器)
- 提供增量构建 - 用于学习或调试,呈现逐步查询构建(见第5a阶段)
- 解释查询 - 它的作用,如何解释结果
- 优先考虑性能 - 特定选择器,早期过滤,更简单的解析器
版本说明
- 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)