510 lines
20 KiB
Markdown
510 lines
20 KiB
Markdown
# CLAUDE.md — monitor.tlyq.ai 告警监控中心
|
||
|
||
## 项目概述
|
||
|
||
monitor-ai 是独立部署的统一告警监控中心,监控 tlyq.ai 基础设施所有容器(Authelia、Redis、LLDAP、OA、assets、issue、Gitea、Nginx、www、cloud、token)的健康状态,通过企业微信 Webhook 推送告警。部署在腾讯云(txjp 服务器),域名 `monitor.tlyq.ai`。
|
||
|
||
---
|
||
|
||
## 快速参考
|
||
|
||
| 属性 | 值 |
|
||
|------|-----|
|
||
| 站点域名 | `monitor.tlyq.ai` |
|
||
| 服务器 | txjp(IP: 43.133.38.210) |
|
||
| 代码路径 | `/root/docker/monitor-ai/` |
|
||
| 本地端口 | 6181 |
|
||
| 容器名 | `monitor-ai` |
|
||
| 数据库 | SQLite:`data/monitor.db` |
|
||
| 默认账号 | `localadmin` / 首次部署自动生成 |
|
||
|
||
### 常用命令
|
||
|
||
```bash
|
||
cd /Users/niuniu/programs/docker/monitor-ai
|
||
npm run dev # 本地开发(http://localhost:6181)
|
||
npm run build # 生产构建
|
||
npm run start # 启动生产服务
|
||
```
|
||
|
||
---
|
||
|
||
## 技术栈
|
||
|
||
| 技术 | 版本 | 用途 |
|
||
|------|------|------|
|
||
| Next.js | 15 App Router | Web 框架(standalone 输出) |
|
||
| SQLite | 3.x | 数据库(通过 `execFileSync` + `sqlite3` CLI) |
|
||
| Tailwind CSS | v4 | 样式(`@tailwindcss/postcss`) |
|
||
| lucide-react | ^1.8.0 | 图标库 |
|
||
| ldapts | ^6.0.0 | LDAP 认证客户端 |
|
||
| openid-client | ^5.7.1 | OIDC 认证 |
|
||
| tsx | ^4.0.0 | Worker TypeScript 执行 |
|
||
|
||
---
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
monitor-ai/
|
||
├── Dockerfile # 两阶段构建(node:22-alpine)
|
||
├── docker-compose.yml # 容器编排(webnet external)
|
||
├── entrypoint.sh # Docker 入口(双进程守护:Worker + Server)
|
||
├── next.config.ts # output: standalone, transpilePackages
|
||
├── shared -> ../shared # 共享库符号链接
|
||
├── scripts/
|
||
│ ├── monitor-worker.ts # Worker 独立入口
|
||
│ ├── deploy-monitor.sh # 部署脚本
|
||
│ └── monitor-watchdog.sh # 健康检查兜底脚本
|
||
├── src/
|
||
│ ├── middleware.ts # Edge Runtime 路由守卫
|
||
│ ├── app/
|
||
│ │ ├── page.tsx # 仪表盘(四层:标题 + 状态条 + KPI + 服务卡片)
|
||
│ │ ├── login/page.tsx # 登录页
|
||
│ │ ├── services/page.tsx # 服务管理
|
||
│ │ ├── settings/page.tsx # 告警设置
|
||
│ │ ├── alerts/page.tsx # 告警历史
|
||
│ │ ├── status-history/page.tsx # 状态变更历史
|
||
│ │ ├── admin/ # 管理页面(users/roles/audit-logs)
|
||
│ │ └── api/ # API 路由
|
||
│ ├── components/
|
||
│ │ ├── Sidebar.tsx # 侧边栏导航
|
||
│ │ ├── ThemeProvider.tsx # 主题上下文
|
||
│ │ └── ThemeToggle.tsx # 主题切换
|
||
│ └── lib/
|
||
│ ├── config.ts # 配置常量
|
||
│ ├── db.ts # 数据库操作封装(execFileSync + escapeSql)
|
||
│ ├── auth-config.ts # 认证配置
|
||
│ ├── permissions.ts # RBAC 权限定义
|
||
│ ├── audit.ts # 审计日志封装
|
||
│ └── monitor-worker.ts # MonitorWorker 核心类
|
||
└── data/
|
||
└── monitor.db # SQLite 数据库
|
||
```
|
||
|
||
---
|
||
|
||
## 关键文件
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `src/lib/monitor-worker.ts` | MonitorWorker 核心类(30s tick,健康检查 + 状态管理 + 告警推送) |
|
||
| `src/lib/db.ts` | SQLite 操作封装(execFileSync + escapeSql,无 ORM) |
|
||
| `src/lib/permissions.ts` | RBAC 权限定义(11 个权限点,admin/editor/viewer/localadmin) |
|
||
| `src/lib/audit.ts` | 审计日志封装(调用 `@shared/lib/audit`) |
|
||
| `src/lib/auth-config.ts` | 认证配置(OIDC + LDAP) |
|
||
| `src/middleware.ts` | Edge Runtime 路由守卫(Cookie JWT 验证,公开/管理路径控制) |
|
||
| `scripts/monitor-worker.ts` | Worker 独立入口(信号处理、优雅退出) |
|
||
| `entrypoint.sh` | Docker 入口(双进程守护:Worker + Server,任一退出则容器退出) |
|
||
| `shared/lib/alert/` | 告警引擎(AlertManager、HealthChecker、类型定义) |
|
||
| `shared/lib/wechat/` | 企业微信推送(WeChatPusher、消息格式化) |
|
||
|
||
---
|
||
|
||
## 数据库 Schema
|
||
|
||
### 表概览
|
||
|
||
| 表名 | 说明 | 来源 |
|
||
|------|------|------|
|
||
| `services` | 被监控服务列表 | `@shared/lib/db/alert-schema` |
|
||
| `alert_channels` | Webhook 告警渠道配置 | `@shared/lib/db/alert-schema` |
|
||
| `alert_settings` | 全局设置 + 冷却状态持久化 | `@shared/lib/db/alert-schema` |
|
||
| `status_history` | 服务状态变更事件 | `@shared/lib/db/alert-schema` |
|
||
| `alert_history` | 告警推送记录 | `@shared/lib/db/alert-schema` |
|
||
| `users` | 用户账号 | `src/lib/db.ts`(内联) |
|
||
| `permissions` | 权限定义 | `src/lib/db.ts`(内联) |
|
||
| `role_permissions` | 角色-权限映射 | `src/lib/db.ts`(内联) |
|
||
| `audit_logs` | 审计日志 | `@shared/lib/audit/audit-schema` |
|
||
|
||
### services 表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | INTEGER PK | 主键 |
|
||
| `name` | TEXT | 服务名称 |
|
||
| `category` | TEXT | 分类(endpoint / container / custom) |
|
||
| `alert_level` | TEXT | 告警级别(critical / warning / info) |
|
||
| `checks` | TEXT | 检查配置(JSON 数组,HealthCheckConfig[]) |
|
||
| `check_interval` | INTEGER | 检查间隔秒数(默认 30) |
|
||
| `check_timeout` | INTEGER | 检查超时秒数(默认 10) |
|
||
| `enabled` | INTEGER | 是否启用(默认 1) |
|
||
| `current_status` | TEXT | 当前状态(normal / abnormal / unknown) |
|
||
| `status_since` | TEXT | 状态持续起始时间 |
|
||
| `display_order` | INTEGER | 显示排序 |
|
||
|
||
### alert_channels 表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | INTEGER PK | 主键 |
|
||
| `name` | TEXT | 渠道名称 |
|
||
| `channel_type` | TEXT | 渠道类型(默认 'wechat') |
|
||
| `webhook_url` | TEXT | Webhook 地址 |
|
||
| `enabled` | INTEGER | 是否启用 |
|
||
| `level_critical` | INTEGER | 是否接收 critical 告警 |
|
||
| `level_warning` | INTEGER | 是否接收 warning 告警 |
|
||
| `level_info` | INTEGER | 是否接收 info 告警 |
|
||
| `quiet_enabled` | INTEGER | 是否启用免打扰 |
|
||
| `quiet_start` | TEXT | 免打扰开始时间 |
|
||
| `quiet_end` | TEXT | 免打扰结束时间 |
|
||
| `quiet_bypass_critical` | INTEGER | critical 是否绕过免打扰 |
|
||
| `cooldown_minutes` | INTEGER | 冷却时间(分钟) |
|
||
|
||
### status_history 表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | INTEGER PK | 主键 |
|
||
| `service_id` | INTEGER FK | 关联服务 |
|
||
| `from_status` | TEXT | 原状态 |
|
||
| `to_status` | TEXT | 新状态 |
|
||
| `started_at` | TEXT | 状态开始时间 |
|
||
| `ended_at` | TEXT | 状态结束时间 |
|
||
| `duration_seconds` | INTEGER | 持续时长 |
|
||
| `error_message` | TEXT | 错误信息 |
|
||
| `failed_checks` | TEXT | 失败检查详情(JSON) |
|
||
| `truncated_by_restart` | INTEGER | 是否被重启截断 |
|
||
|
||
### alert_history 表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | INTEGER PK | 主键 |
|
||
| `channel_id` | INTEGER FK | 告警渠道 |
|
||
| `service_id` | INTEGER FK | 关联服务 |
|
||
| `status_event_id` | INTEGER FK | 关联状态事件 |
|
||
| `alert_type` | TEXT | 告警类型(alert / recovery / flapping) |
|
||
| `level` | TEXT | 告警级别 |
|
||
| `title` | TEXT | 标题 |
|
||
| `content` | TEXT | 内容 |
|
||
| `sent_at` | TEXT | 发送时间 |
|
||
| `success` | INTEGER | 是否成功 |
|
||
| `response_code` | INTEGER | HTTP 响应码 |
|
||
|
||
### users 表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | INTEGER PK | 主键 |
|
||
| `username` | TEXT UNIQUE | 用户名 |
|
||
| `display_name` | TEXT | 显示名 |
|
||
| `email` | TEXT | 邮箱 |
|
||
| `role` | TEXT | 角色(admin / editor / viewer) |
|
||
| `password_hash` | TEXT | 密码哈希 |
|
||
| `is_active` | INTEGER | 是否启用 |
|
||
|
||
默认用户:`localadmin`(admin 角色,BCrypt 密码哈希)
|
||
|
||
### 预置角色
|
||
|
||
| 角色 | 权限 | 说明 |
|
||
|------|------|------|
|
||
| `admin` | 全部 11 个权限 | 管理员 |
|
||
| `editor` | dashboard:view, services:view, alerts:view, status_history:view, status_history:stats | 编辑者 |
|
||
| `viewer` | dashboard:view, services:view, status_history:view | 只读 |
|
||
| `localadmin` | 硬编码绕过(hasPermission 始终返回 true) | 应急管理员 |
|
||
|
||
### 权限列表
|
||
|
||
`dashboard:view`、`services:view`、`services:manage`、`alerts:view`、`alerts:manage`、`status_history:view`、`status_history:stats`、`audit:view`、`users:view`、`users:manage`、`roles:manage`
|
||
|
||
---
|
||
|
||
## API 路由
|
||
|
||
### 公开 API
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/health` | 自身健康检查(返回 `{status:'OK'}`) |
|
||
|
||
### 认证
|
||
|
||
登录逻辑:OIDC SSO 优先 + LDAP 本地登录 + localadmin 应急用户。
|
||
登录成功签发 `tlyq_session` cookie(共享 JWT,domain=.tlyq.ai)。
|
||
中间件验证 JWT payload(Edge Runtime,不解密签名,仅解码 payload 检查过期时间)。
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/auth/login/oidc` | OIDC SSO 重定向到 Authelia |
|
||
| POST | `/api/auth/login` | LDAP 或 localadmin 登录 |
|
||
| GET | `/api/auth/callback` | OIDC 回调处理 |
|
||
| POST | `/api/auth/logout` | 登出(清除 cookie,重定向 Authelia end_session) |
|
||
| GET | `/api/auth/me` | 当前用户信息 |
|
||
|
||
### 服务管理
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
|------|------|------|------|
|
||
| GET | `/api/services` | 登录 | 服务列表(含解析后的 JSON checks) |
|
||
| POST | `/api/services` | services:manage | 新增服务 |
|
||
| PUT | `/api/services/[id]` | services:manage | 更新服务 |
|
||
| DELETE | `/api/services/[id]` | services:manage | 删除服务 |
|
||
| POST | `/api/services/[id]/check` | services:manage | 手动触发单次健康检查 |
|
||
|
||
### 告警渠道
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
|------|------|------|------|
|
||
| GET | `/api/alert-channels` | alerts:manage | 渠道列表(webhook_url 脱敏) |
|
||
| POST | `/api/alert-channels` | alerts:manage | 新增渠道 |
|
||
| PUT | `/api/alert-channels/[id]` | alerts:manage | 更新渠道 |
|
||
| DELETE | `/api/alert-channels/[id]` | alerts:manage | 删除渠道 |
|
||
| POST | `/api/alert-channels/[id]/test` | alerts:manage | 测试推送 |
|
||
|
||
### 告警历史 / 状态历史
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
|------|------|------|------|
|
||
| GET | `/api/alerts` | alerts:view | 告警历史(分页) |
|
||
| GET | `/api/status-history` | 登录 | 状态变更历史(分页,可按 service_id 筛选) |
|
||
| GET | `/api/status` | 登录 | 所有服务实时状态汇总 |
|
||
|
||
### 内部 API(x-internal-key 鉴权)
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/api/internal/users` | 返回用户列表 |
|
||
| POST | `/api/internal/users` | OA 同步用户角色 |
|
||
|
||
### 管理
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
|------|------|------|------|
|
||
| GET | `/api/admin/worker-status` | dashboard:view | Worker 运行状态 |
|
||
|
||
---
|
||
|
||
## Worker 架构
|
||
|
||
### MonitorWorker 核心类
|
||
|
||
位置:`src/lib/monitor-worker.ts`
|
||
|
||
```
|
||
MonitorWorker
|
||
├── HealthChecker(@shared/lib/alert/health-checker)
|
||
│ ├── HttpChecker — HTTP 状态码 + 响应体匹配
|
||
│ └── DockerChecker — docker ps 容器状态检查
|
||
├── AlertManager(@shared/lib/alert/alert-manager)
|
||
│ ├── evaluate() — 三阶段告警决策(级别匹配 → 免打扰 → 冷却)
|
||
│ └── CooldownProvider — alert_settings 表持久化冷却状态
|
||
└── WeChatPusher(@shared/lib/wechat/wechat-pusher)
|
||
└── pushMarkdown() — 企业微信 Webhook 推送
|
||
```
|
||
|
||
### 运行机制
|
||
|
||
| 阶段 | 间隔 | 说明 |
|
||
|------|------|------|
|
||
| 健康检查 | 30 秒 tick | 遍历所有 enabled 服务,并发执行检查(Promise.allSettled) |
|
||
| 抖动检测 | 10 分钟窗口 | 同一服务 10 分钟内状态切换 >= 5 次 → 触发 flapping 告警,抑制后续告警 |
|
||
| 持续异常提醒 | 30 分钟 | 服务持续 abnormal 状态,每 30 分钟发送提醒 |
|
||
| 恢复通知 | 即时 | 服务恢复正常时发送 recovery 通知,绕过免打扰和冷却 |
|
||
| WAL 检查点 | 1 小时 | 被动 WAL checkpoint(PASSIVE) |
|
||
| 数据清理 | 每天 | 删除 180 天前的 status_history 和 alert_history(每批 LIMIT 1000) |
|
||
|
||
### Docker 入口(entrypoint.sh)
|
||
|
||
```
|
||
entrypoint.sh
|
||
├── npx tsx scripts/monitor-worker.ts & # 后台启动 Worker
|
||
├── node server.js & # 后台启动 Next.js Server
|
||
└── 守护循环:任一进程退出则容器退出 # 保证双进程存活
|
||
└── trap SIGTERM/SIGINT → 清理退出
|
||
```
|
||
|
||
---
|
||
|
||
## 认证机制
|
||
|
||
- **OIDC SSO**:通过 Authelia 进行 PKCE 授权码流程,登录成功后签发 `tlyq_session` 共享 JWT cookie
|
||
- **LDAP 本地登录**:通过 LLDAP 进行 bind 认证,签发 `tlyq_session` cookie
|
||
- **localadmin**:纯本地 BCrypt 认证,不依赖 LLDAP/OIDC,用于应急登录
|
||
- **Edge Runtime 中间件**:`src/middleware.ts` 运行在 Edge Runtime,使用 `atob` 解码 JWT payload 检查过期时间,不验证签名(签名验证在 route handler 层)
|
||
|
||
---
|
||
|
||
## 环境配置
|
||
|
||
### 本地与云端差异
|
||
|
||
| 环境变量 | 本地开发 | 云服务器(txjp) | 说明 |
|
||
|---------|---------|----------------|------|
|
||
| `DATABASE_PATH` | `./data/monitor.db` | `/app/data/monitor.db` | Docker volume 挂载 |
|
||
| `MONITOR_MODE` | `dev` | `local` | 运行模式 |
|
||
| `AUTHELIA_URL` | `https://127.0.0.1:6180` | `https://sso.tlyq.ai` | Authelia 地址 |
|
||
| `OIDC_CLIENT_ID` | `monitor-oidc` | 同 | OIDC 客户端 ID |
|
||
| `OIDC_CLIENT_SECRET` | 本地生成的值 | 服务器生成的值 | OIDC 客户端密钥(每个环境独立) |
|
||
| `OIDC_REDIRECT_URI` | `http://localhost:6181/api/auth/callback` | `https://monitor.tlyq.ai/api/auth/callback` | OIDC 回调地址 |
|
||
| `JWT_SECRET` | `dev-jwt-secret-change-in-production` | 部署脚本自动生成 | JWT 签名密钥 |
|
||
| `COOKIE_DOMAIN` | `.tlyq.ai` | 同 | Cookie 域 |
|
||
| `LDAP_URL` | `ldap://ldap-ai:3890` | `ldap://ldap-ai:3890` | LLDAP 地址(Docker 内网) |
|
||
| `LOCALADMIN_PASSWORD` | `admin123` | 部署脚本自动生成 | 应急管理员密码 |
|
||
| `NODE_TLS_REJECT_UNAUTHORIZED` | `0` | `0` | TLS 证书验证(Authelia 自签名) |
|
||
|
||
### `.env.local` 示例
|
||
|
||
```bash
|
||
DATABASE_PATH=./data/monitor.db
|
||
MONITOR_MODE=dev
|
||
AUTHELIA_URL=https://127.0.0.1:6180
|
||
OIDC_CLIENT_ID=monitor-oidc
|
||
OIDC_CLIENT_SECRET=<本地生成的值>
|
||
OIDC_REDIRECT_URI=http://localhost:6181/api/auth/callback
|
||
JWT_SECRET=dev-jwt-secret-change-in-production
|
||
COOKIE_DOMAIN=.tlyq.ai
|
||
LDAP_URL=ldap://ldap-ai:3890
|
||
LOCALADMIN_PASSWORD=admin123
|
||
NODE_TLS_REJECT_UNAUTHORIZED=0
|
||
```
|
||
|
||
---
|
||
|
||
## 共享库引用
|
||
|
||
| 库 | 用途 | 导入路径 |
|
||
|------|------|------|
|
||
| `@shared/lib/auth/jwt-v2` | JWT 签名/验证(HS256,含 iss) | `import { signJwtV2, verifyJwtV2 } from '@shared/lib/auth/jwt-v2'` |
|
||
| `@shared/lib/auth/jwt` | JWT 签名/验证(V1 兼容,无 iss) | `import { signJwt, verifyJwt } from '@shared/lib/auth/jwt'` |
|
||
| `@shared/lib/auth/middleware-v2` | 路由守卫工厂(V2:单 cookie 模型) | `import { createMiddlewareV2 } from '@shared/lib/auth/middleware-v2'` |
|
||
| `@shared/lib/auth/middleware` | 路由守卫工厂(V1,已废弃) | `import { createMiddleware } from '@shared/lib/auth/middleware'` |
|
||
| `@shared/lib/auth/oidc` | OIDC PKCE 流程 | `import { discoverOidcConfig, buildAuthorizeUrl } from '@shared/lib/auth/oidc'` |
|
||
| `@shared/lib/auth/ldap` | LDAP 认证 | `import { ldapAuth } from '@shared/lib/auth/ldap'` |
|
||
| `@shared/lib/alert/alert-manager` | 告警决策引擎 | `import { AlertManager } from '@shared/lib/alert/alert-manager'` |
|
||
| `@shared/lib/alert/health-checker` | 健康检查引擎 | `import { HealthChecker, HttpChecker, DockerChecker } from '@shared/lib/alert/health-checker'` |
|
||
| `@shared/lib/audit/write-audit-log` | 审计日志 | `import { writeAuditLog } from '@shared/lib/audit/write-audit-log'` |
|
||
| `@shared/lib/wechat/wechat-pusher` | 企业微信推送 | `import { WeChatPusher } from '@shared/lib/wechat/wechat-pusher'` |
|
||
| `@shared/lib/wechat/message-formatter` | 消息格式化 | `import { formatAlertLevel } from '@shared/lib/wechat/message-formatter'` |
|
||
| `@shared/lib/db/alert-schema` | 数据库 Schema 常量 | `import { ALL_TABLES_SQL } from '@shared/lib/db/alert-schema'` |
|
||
| `@shared/ui` | UI 组件库 | `import { Button, Card, Badge } from '@shared/ui'` |
|
||
| `@shared/ui/login-page` | 统一登录页 | `import LoginPage from '@shared/ui/login-page'` |
|
||
|
||
> **路径映射**:`tsconfig.json` 中配置 `"@shared/*": ["./shared/*"]`,`shared` 是指向 `../shared` 的符号链接。
|
||
|
||
---
|
||
|
||
## 关键设计决策
|
||
|
||
### execFileSync 数组参数
|
||
|
||
数据库操作使用 `execFileSync('sqlite3', [dbPath, '-json', sql])` 而非 ORM。SQL 通过数组参数传递,避免 shell 注入。所有用户输入通过 `escapeSql()` 函数转义(单引号双写)。
|
||
|
||
### Edge Runtime 中间件
|
||
|
||
`src/middleware.ts` 运行在 Edge Runtime,不能使用 Node.js `crypto` 模块。JWT 验证仅解码 payload 检查过期时间,签名验证留给 route handler 层处理。
|
||
|
||
### 双进程守护
|
||
|
||
`entrypoint.sh` 同时启动 Worker 和 Server,使用 bash 守护循环监控。任一进程退出则整个容器退出,由 Docker 重启策略接管。
|
||
|
||
### 冷却状态持久化
|
||
|
||
告警冷却状态存储在 `alert_settings` 表中(key 格式:`cooldown:{channel_id}:{service_id}:{level}`),容器重启后冷却状态不丢失。
|
||
|
||
---
|
||
|
||
## Docker 部署
|
||
|
||
```
|
||
txjp 服务器
|
||
├── monitor-ai(容器) ← Next.js standalone + Worker,监听 6181
|
||
├── nginx-ai ← 反向代理 monitor.tlyq.ai → monitor-ai:6181
|
||
└── webnet(external) ← 共享网络
|
||
```
|
||
|
||
部署:`bash deploy-monitor.sh`(本地模式)或 `bash deploy-monitor.sh --remote --host <IP>`。
|
||
|
||
源码打包上传 → 服务器 `npm install` + `npm run build` → `.next` 挂载进容器生效。
|
||
|
||
### 生产环境变量
|
||
|
||
```bash
|
||
DATABASE_PATH=/app/data/monitor.db
|
||
MONITOR_MODE=local
|
||
AUTHELIA_URL=https://sso.tlyq.ai
|
||
OIDC_CLIENT_ID=monitor-oidc
|
||
OIDC_CLIENT_SECRET=<部署脚本自动生成>
|
||
OIDC_REDIRECT_URI=https://monitor.tlyq.ai/api/auth/callback
|
||
JWT_SECRET=<部署脚本自动生成>
|
||
COOKIE_DOMAIN=.tlyq.ai
|
||
LDAP_URL=ldap://ldap-ai:3890
|
||
LOCALADMIN_PASSWORD=<部署脚本自动生成>
|
||
NODE_ENV=production
|
||
NODE_TLS_REJECT_UNAUTHORIZED=0
|
||
```
|
||
|
||
---
|
||
|
||
## 开发规范
|
||
|
||
- **新增 API**:在 `src/app/api/` 下创建路由 → 顶部调用 `initDatabase()` → `getCurrentUser()` 验证 → `checkPermission()` 校验
|
||
- **新增页面**:在 `src/app/` 下创建 → 布局由 `client-layout.tsx` 提供(Sidebar + ThemeProvider)
|
||
- **权限格式**:`resource:action`,如 `checkPermission(user, 'services:manage')`
|
||
- **审计日志**:所有写操作 API(POST/PUT/DELETE)必须添加审计日志:
|
||
```typescript
|
||
import { writeAuditLog } from '@/lib/audit'
|
||
|
||
writeAuditLog({
|
||
userId: user.id,
|
||
action: 'create' | 'update' | 'delete',
|
||
entityType: 'service' | 'alert_channel' | 'user',
|
||
entityId: id,
|
||
details: { ... },
|
||
ipAddress: getClientIP(request)
|
||
})
|
||
```
|
||
- **日期处理(时区规范)**:整个系统统一使用 UTC+8(北京时间)。必须遵守:
|
||
1. **JavaScript/TypeScript**:禁止使用 `Date.toISOString()` 格式化本地日期,应使用本地时间方法拼接
|
||
2. **SQLite**:所有 `datetime('now')` 必须写成 `datetime('now', '+8 hours')`
|
||
3. **INSERT 时间列**:数据库表 DEFAULT 已统一为 `datetime('now', '+8 hours')`,INSERT 时可省略
|
||
|
||
---
|
||
|
||
## 健康检查兜底
|
||
|
||
`scripts/monitor-watchdog.sh` 是独立于 monitor-ai 的兜底脚本,通过 crontab 每 5 分钟执行:
|
||
|
||
```bash
|
||
*/5 * * * * /root/docker/monitor-ai/scripts/monitor-watchdog.sh >> /var/log/monitor-watchdog.log 2>&1
|
||
```
|
||
|
||
当 `/api/health` 连续失败时,直接通过企业微信 Webhook 发送告警,并尝试重启容器。
|
||
|
||
---
|
||
|
||
## 故障排查
|
||
|
||
```bash
|
||
# 容器日志
|
||
ssh txjp "docker logs monitor-ai"
|
||
|
||
# Worker 日志(实时)
|
||
ssh txjp "docker logs -f monitor-ai 2>&1 | grep -i worker"
|
||
|
||
# 数据库查看
|
||
ssh txjp "docker exec monitor-ai sqlite3 /app/data/monitor.db 'SELECT id, name, current_status FROM services;'"
|
||
|
||
# 健康检查
|
||
ssh txjp "curl -s -k https://monitor.tlyq.ai/api/health"
|
||
|
||
# 手动触发检查
|
||
ssh txjp "docker exec monitor-ai sqlite3 /app/data/monitor.db 'UPDATE services SET current_status=\"unknown\";'"
|
||
|
||
# 重建镜像(新增依赖后)
|
||
ssh txjp "cd /root/docker/monitor-ai && docker compose build --no-cache && docker compose down && docker compose up -d"
|
||
```
|
||
|
||
---
|
||
|
||
## Git Tag 规范
|
||
|
||
使用日期版本号 `vYYYY.MM.DD`(如 `v2026.07.01`)。提交后打 tag 再推送:
|
||
|
||
```bash
|
||
git tag v$(date +%Y.%m.%d) && git push origin main && git push origin v$(date +%Y.%m.%d)
|
||
```
|
||
|
||
同一天多次提交只打一个 tag。详见根目录 `CLAUDE.md`。
|