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

12 KiB
Raw Blame History

Loki 日志收集系统集成文档

概述

本项目已集成 Grafana Loki 日志收集系统,支持两种日志收集模式:

  1. Docker stdio 收集(推荐)- 从容器标准输出/错误收集日志
  2. 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

  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 查询示例

基础查询

# 查询所有应用日志
{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 收集(默认,推荐)

特点:

  • 无需修改应用代码
  • 自动收集容器标准输出/错误
  • 性能影响极小
  • 配置简单

工作原理:

  1. 应用将日志输出到 stdout/stderr
  2. Docker Engine 捕获日志
  3. Promtail 通过 Docker API 读取日志
  4. 日志发送到 Loki 存储

配置:

  • 应用容器需要添加标签:
    labels:
      logging: "promtail"
      logging_jobname: "functional-scaffold-app"
    

模式 2: Log 文件收集(备用)

特点:

  • 日志持久化到文件
  • 支持日志轮转
  • 适合需要本地日志文件的场景

启用方式:

  1. 修改 deployment/docker-compose.yml

    environment:
      - LOG_FILE_ENABLED=true
      - LOG_FILE_PATH=/var/log/app/app.log
    
  2. 重启服务:

    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 中验证

  1. 访问 http://localhost:3000/explore
  2. 选择 Loki 数据源
  3. 输入查询: {job="functional-scaffold-app"}
  4. 应该能看到应用日志

故障排查

问题 1: 看不到日志

检查步骤:

  1. 确认 Promtail 正在运行:

    docker-compose ps promtail
    
  2. 检查 Promtail 日志:

    docker-compose logs promtail
    
  3. 确认应用容器有正确的标签:

    docker inspect functional-scaffold-app-1 | grep -A 5 Labels
    
  4. 检查 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 响应缓慢
  • 磁盘空间不足

解决方案:

  1. 调整日志保留期:

    # monitoring/loki.yaml
    limits_config:
      retention_period: 72h  # 改为 3 天
    
  2. 增加摄入速率限制:

    limits_config:
      ingestion_rate_mb: 5  # 降低到 5MB/s
    
  3. 添加日志过滤:

    # monitoring/promtail.yaml
    pipeline_stages:
      - match:
          selector: '{job="functional-scaffold-app"}'
          stages:
            - drop:
                expression: ".*healthz.*"  # 丢弃健康检查日志
    

问题 4: 文件模式下看不到日志

检查步骤:

  1. 确认文件日志已启用:

    docker-compose exec app env | grep LOG_FILE
    
  2. 检查日志文件是否存在:

    docker-compose exec app ls -lh /var/log/app/
    
  3. 检查 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 格式,支持字段提取 高性能 - 低资源占用,快速查询 易于扩展 - 支持自定义标签和过滤规则

如有问题,请参考故障排查章节或查阅官方文档。