main:删除 Grafana 仪表板配置文件
更新内容: - 移除 `dashboard.json` 文件,清理不再需要的 Grafana 仪表板配置。 - 简化项目目录结构,删除多余的监控配置以优化维护。
This commit is contained in:
564
docs/loki-integration.md
Normal file
564
docs/loki-integration.md
Normal file
@@ -0,0 +1,564 @@
|
||||
# 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 格式,支持字段提取
|
||||
✅ **高性能** - 低资源占用,快速查询
|
||||
✅ **易于扩展** - 支持自定义标签和过滤规则
|
||||
|
||||
如有问题,请参考故障排查章节或查阅官方文档。
|
||||
Reference in New Issue
Block a user