# 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 格式,支持字段提取 ✅ **高性能** - 低资源占用,快速查询 ✅ **易于扩展** - 支持自定义标签和过滤规则 如有问题,请参考故障排查章节或查阅官方文档。