更新内容: - 移除 `dashboard.json` 文件,清理不再需要的 Grafana 仪表板配置。 - 简化项目目录结构,删除多余的监控配置以优化维护。
12 KiB
12 KiB
Loki 日志收集系统集成文档
概述
本项目已集成 Grafana Loki 日志收集系统,支持两种日志收集模式:
- Docker stdio 收集(推荐)- 从容器标准输出/错误收集日志
- Log 文件收集(备用)- 从日志文件收集日志
架构
应用容器 (stdout/stderr)
↓
Docker Engine
↓
Promtail (日志采集器)
↓
Loki (日志存储)
↓
Grafana (可视化)
快速开始
1. 启动服务
cd deployment
docker-compose up -d
这将启动以下服务:
- app: 应用服务 (端口 8111)
- loki: 日志存储服务 (端口 3100)
- promtail: 日志采集服务 (端口 9080)
- grafana: 可视化服务 (端口 3000)
- prometheus: 指标收集服务 (端口 9090)
- redis: 缓存服务 (端口 6380)
2. 访问 Grafana
- 打开浏览器访问 http://localhost:3000
- 使用默认凭据登录:
- 用户名:
admin - 密码:
admin
- 用户名:
- 首次登录后建议修改密码
3. 查看日志
方式 1: 使用预配置的日志仪表板
- 在 Grafana 左侧菜单点击 Dashboards
- 选择 日志监控 仪表板
- 查看以下面板:
- 日志流 (实时): 实时日志流
- 日志量趋势(按级别): 时间序列图表
- 日志级别分布: 按级别统计
- 错误日志: 只显示 ERROR 级别日志
方式 2: 使用 Explore 功能
- 在 Grafana 左侧菜单点击 Explore (指南针图标)
- 选择 Loki 数据源
- 输入 LogQL 查询语句(见下文)
LogQL 查询示例
基础查询
# 查询所有应用日志
{job="functional-scaffold-app"}
# 查询特定级别的日志
{job="functional-scaffold-app", level="ERROR"}
{job="functional-scaffold-app", level="INFO"}
# 查询特定容器的日志
{container="functional-scaffold-app-1"}
文本过滤
# 包含特定文本
{job="functional-scaffold-app"} |= "request_id"
# 不包含特定文本
{job="functional-scaffold-app"} != "healthz"
# 正则表达式匹配
{job="functional-scaffold-app"} |~ "error|exception"
# 正则表达式不匹配
{job="functional-scaffold-app"} !~ "debug|trace"
JSON 字段提取
# 提取 request_id 字段
{job="functional-scaffold-app"} | json | request_id != ""
# 提取并过滤特定 request_id
{job="functional-scaffold-app"} | json | request_id = "abc123"
# 提取 logger 字段
{job="functional-scaffold-app"} | json | logger = "functional_scaffold.api.routes"
聚合查询
# 统计日志数量
count_over_time({job="functional-scaffold-app"}[5m])
# 按级别统计
sum by (level) (count_over_time({job="functional-scaffold-app"}[5m]))
# 计算错误率
sum(rate({job="functional-scaffold-app", level="ERROR"}[5m]))
/
sum(rate({job="functional-scaffold-app"}[5m]))
日志收集模式
模式 1: Docker stdio 收集(默认,推荐)
特点:
- 无需修改应用代码
- 自动收集容器标准输出/错误
- 性能影响极小
- 配置简单
工作原理:
- 应用将日志输出到 stdout/stderr
- Docker Engine 捕获日志
- Promtail 通过 Docker API 读取日志
- 日志发送到 Loki 存储
配置:
- 应用容器需要添加标签:
labels: logging: "promtail" logging_jobname: "functional-scaffold-app"
模式 2: Log 文件收集(备用)
特点:
- 日志持久化到文件
- 支持日志轮转
- 适合需要本地日志文件的场景
启用方式:
-
修改
deployment/docker-compose.yml:environment: - LOG_FILE_ENABLED=true - LOG_FILE_PATH=/var/log/app/app.log -
重启服务:
docker-compose up -d app
日志文件配置:
- 最大文件大小: 100MB
- 保留备份数: 5 个
- 总存储空间: 最多 500MB
配置说明
Loki 配置 (monitoring/loki.yaml)
limits_config:
retention_period: 168h # 日志保留 7 天
ingestion_rate_mb: 10 # 摄入速率限制 10MB/s
ingestion_burst_size_mb: 20 # 突发大小 20MB
可调整参数:
retention_period: 日志保留时间(默认 7 天)ingestion_rate_mb: 每秒摄入速率限制ingestion_burst_size_mb: 突发流量大小
Promtail 配置 (monitoring/promtail.yaml)
Docker stdio 收集配置:
scrape_configs:
- job_name: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
filters:
- name: label
values: ["logging=promtail"]
文件收集配置:
scrape_configs:
- job_name: app_files
static_configs:
- targets:
- localhost
labels:
job: functional-scaffold-app-files
__path__: /var/log/app/*.log
验证和测试
1. 检查服务状态
# 查看所有服务
docker-compose ps
# 检查 Loki 健康状态
curl http://localhost:3100/ready
# 检查 Promtail 健康状态
curl http://localhost:9080/ready
2. 生成测试日志
# 发送测试请求
curl -X POST http://localhost:8111/invoke \
-H "Content-Type: application/json" \
-d '{"algorithm": "PrimeChecker", "params": {"number": 17}}'
3. 查询日志
# 使用 Loki API 查询
curl -G -s "http://localhost:3100/loki/api/v1/query_range" \
--data-urlencode 'query={job="functional-scaffold-app"}' \
--data-urlencode 'limit=10' \
| jq '.data.result'
4. 在 Grafana 中验证
- 访问 http://localhost:3000/explore
- 选择 Loki 数据源
- 输入查询:
{job="functional-scaffold-app"} - 应该能看到应用日志
故障排查
问题 1: 看不到日志
检查步骤:
-
确认 Promtail 正在运行:
docker-compose ps promtail -
检查 Promtail 日志:
docker-compose logs promtail -
确认应用容器有正确的标签:
docker inspect functional-scaffold-app-1 | grep -A 5 Labels -
检查 Loki 是否接收到日志:
curl -G -s "http://localhost:3100/loki/api/v1/label/job/values" | jq
问题 2: Promtail 无法访问 Docker socket
错误信息:
permission denied while trying to connect to the Docker daemon socket
解决方案:
在 macOS/Linux 上,确保 Docker socket 权限正确:
sudo chmod 666 /var/run/docker.sock
或者将 Promtail 容器添加到 docker 组(Linux):
promtail:
user: root
group_add:
- docker
问题 3: 日志量过大
症状:
- Loki 响应缓慢
- 磁盘空间不足
解决方案:
-
调整日志保留期:
# monitoring/loki.yaml limits_config: retention_period: 72h # 改为 3 天 -
增加摄入速率限制:
limits_config: ingestion_rate_mb: 5 # 降低到 5MB/s -
添加日志过滤:
# monitoring/promtail.yaml pipeline_stages: - match: selector: '{job="functional-scaffold-app"}' stages: - drop: expression: ".*healthz.*" # 丢弃健康检查日志
问题 4: 文件模式下看不到日志
检查步骤:
-
确认文件日志已启用:
docker-compose exec app env | grep LOG_FILE -
检查日志文件是否存在:
docker-compose exec app ls -lh /var/log/app/ -
检查 Promtail 是否能访问日志文件:
docker-compose exec promtail ls -lh /var/log/app/
性能优化
1. 减少日志量
在应用层面:
- 调整日志级别为 WARNING 或 ERROR
- 过滤掉不必要的日志(如健康检查)
# docker-compose.yml
environment:
- LOG_LEVEL=WARNING
在 Promtail 层面:
# monitoring/promtail.yaml
pipeline_stages:
- drop:
expression: ".*healthz.*"
drop_counter_reason: "healthcheck"
2. 优化查询性能
使用标签过滤:
# 好:使用标签过滤(快)
{job="functional-scaffold-app", level="ERROR"}
# 差:使用文本过滤(慢)
{job="functional-scaffold-app"} |= "ERROR"
限制时间范围:
# 查询最近 5 分钟
{job="functional-scaffold-app"}[5m]
# 避免查询过长时间范围
{job="functional-scaffold-app"}[7d] # 慢
3. 存储优化
定期清理旧数据:
# Loki 会自动根据 retention_period 清理
# 也可以手动清理
docker-compose exec loki rm -rf /loki/chunks/*
监控磁盘使用:
docker-compose exec loki du -sh /loki/chunks
高级功能
1. 告警规则
在 Loki 中配置告警规则(需要 Loki Ruler):
# monitoring/loki-rules.yaml
groups:
- name: error_alerts
interval: 1m
rules:
- alert: HighErrorRate
expr: |
sum(rate({job="functional-scaffold-app", level="ERROR"}[5m]))
/
sum(rate({job="functional-scaffold-app"}[5m]))
> 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "错误率过高"
description: "应用错误率超过 5%"
2. 日志导出
导出为 JSON:
curl -G -s "http://localhost:3100/loki/api/v1/query_range" \
--data-urlencode 'query={job="functional-scaffold-app"}' \
--data-urlencode 'start=2024-01-01T00:00:00Z' \
--data-urlencode 'end=2024-01-02T00:00:00Z' \
| jq '.data.result' > logs.json
导出为文本:
curl -G -s "http://localhost:3100/loki/api/v1/query_range" \
--data-urlencode 'query={job="functional-scaffold-app"}' \
| jq -r '.data.result[].values[][1]' > logs.txt
3. 与 Prometheus 集成
在 Grafana 仪表板中同时显示日志和指标:
{
"panels": [
{
"title": "错误率和错误日志",
"targets": [
{
"datasource": "Prometheus",
"expr": "rate(http_requests_total{status=\"error\"}[5m])"
},
{
"datasource": "Loki",
"expr": "{job=\"functional-scaffold-app\", level=\"ERROR\"}"
}
]
}
]
}
最佳实践
1. 日志格式
使用结构化日志(JSON):
logger.info("处理请求", extra={
"request_id": "abc123",
"user_id": "user456",
"duration": 0.123
})
输出:
{
"asctime": "2024-01-01 12:00:00,000",
"name": "functional_scaffold.api.routes",
"levelname": "INFO",
"message": "处理请求",
"request_id": "abc123",
"user_id": "user456",
"duration": 0.123
}
2. 标签策略
好的标签:
- 低基数(值的种类少)
- 用于过滤和分组
- 例如:
level,logger,container
不好的标签:
- 高基数(值的种类多)
- 例如:
request_id,user_id,timestamp
正确做法:
# 使用标签过滤
{job="functional-scaffold-app", level="ERROR"}
# 使用 JSON 提取高基数字段
{job="functional-scaffold-app"} | json | request_id = "abc123"
3. 查询优化
使用时间范围:
{job="functional-scaffold-app"}[5m] # 最近 5 分钟
限制返回行数:
{job="functional-scaffold-app"} | limit 100
使用聚合减少数据量:
sum by (level) (count_over_time({job="functional-scaffold-app"}[5m]))
参考资料
总结
本项目的 Loki 集成提供了:
✅ 开箱即用 - 无需额外配置即可收集日志 ✅ 双模式支持 - Docker stdio(默认)和文件收集 ✅ 自动化配置 - 数据源和仪表板自动加载 ✅ 结构化日志 - JSON 格式,支持字段提取 ✅ 高性能 - 低资源占用,快速查询 ✅ 易于扩展 - 支持自定义标签和过滤规则
如有问题,请参考故障排查章节或查阅官方文档。