Files
FunctionalScaffold/docs/loki-integration.md
Roog (顾新培) 683bf8a6ca main:删除 Grafana 仪表板配置文件
更新内容:
- 移除 `dashboard.json` 文件,清理不再需要的 Grafana 仪表板配置。
- 简化项目目录结构,删除多余的监控配置以优化维护。
2026-02-03 18:38:08 +08:00

565 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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