API 访问日志
「系统管理 → 系统监控 → API 访问日志」(/system/api-access-logs)按请求记录 HTTP 访问事实,支持分页、筛选、详情、导出和手动清除。
工具栏的「清除日志」复用系统调度运行日志的菜单和危险操作确认,提供清除一年前、六个月前、三个月前、一个月前及全部日志。清除权限为 system:api-access-log:clean,调用 DELETE /api/api-access-logs/clean?days=...;days=0 明确表示全部,省略默认 180 天。清除不受列表筛选条件限制,但保持与列表一致的平台管理员和租户视角约束,选定租户时仅清除该租户的日志。服务端冻结初始 ID 边界并分批删除,返回实际删除数量,同时记录清除前数量和删除结果的操作审计;新产生的访问日志不追溯删除。
业务操作前后快照仍由 operation_logs 负责;异常堆栈仍由 error_events 负责。访问日志通过同一 requestId 与它们关联。
采集边界
全局中间件在请求 ID 与链路上下文初始化后、认证和业务门禁之前安装,正常响应、匿名访问、401、403、404、业务 4xx 和服务端 5xx 都可留痕。 操作名称、标识与模块由契约路由派生,无需在每个业务处理器里调用日志写入函数。非契约路由仍保留方法、路径、状态码与耗时。
采集面向 /api/*;健康检查、指标、WebSocket、接口文档以及控制台日志、日志文件、日志查看器等高频读取入口排除采集。 开放网关请求也可在这里定位;开放平台现有调用日志继续承担应用计量和统计,两个模型分别保留。
每条日志包含以下信息:
| 信息 | 字段 |
|---|---|
| 访问人 / 调用方 | 统一访问人 / 调用方 ID(user:<id>、member:<id>、app:<clientId>、device:<id>)、展示名称、管理员 / 会员 / 设备 / 应用的精确关联 ID、访问端类型、凭证方式、模拟登录实际操作人 |
| 请求 | 方法、路径、匹配的路由模板、请求 ID、脱敏查询参数和可采集的 JSON 请求体 |
| 操作 | 契约操作标识、操作名称、模块、请求方法对应的操作类型 |
| 结果 | 最终 HTTP 状态码、处理耗时、异常名称;不复制原始异常消息和堆栈 |
| 节点与客户端 | 服务名、进程角色、主机、PID、IP、位置、User-Agent、系统与浏览器 |
| 时间 | 请求开始时间 createdAt,耗时使用单调时钟计算 |
路径单独保存,不拼接原始查询串;含凭证的路由参数使用路由模板代替实际值。查询参数与请求体按字段名脱敏,密码、Token、Secret、Cookie、签名和验证码等凭证不保留原值。
请求正文只使用 Hono 已经解析的 JSON 缓存,采集器不主动读取或克隆请求流,避免改变上传、体积限制和流式处理的行为。 认证、密码、令牌、签名等凭证路由不采集正文;非 JSON、未被处理器解析的正文、超限正文和 JSON 标量不采集。正文快照有 16 KiB 上限,并限制深度、集合元素和字段数量。 查询快照也有字段数量、单值长度和总字节限制;被裁剪的快照会保留截断标记。
访问日志不保存 Authorization 等请求头、完整响应体、业务变更前后值和异常堆栈。详情中的查询和正文是用于排错的有限快照,不能当作原始报文归档。
查询、权限与导出
共享契约位于 packages/shared/src/platform/contracts/api-access-logs.ts:
| 方法 | 接口 | 权限 |
|---|---|---|
GET | /api/api-access-logs | system:api-access-log:list |
GET | /api/api-access-logs/{id} | system:api-access-log:list |
多租户部署要求平台超级管理员身份,租户超级管理员即使具备同名权限也不能读取日志。平台管理员选择租户视角时,列表、详情与导出同步限定到该租户;单租户部署按功能权限控制。
列表支持访问人 / 调用方名称与统一 ID、管理员 / 会员 / 设备 ID、访问端类型、凭证方式、模块、操作、方法、路径、路由模板、请求 ID 前缀、状态、精确 HTTP 状态码、服务、IP、时间、耗时和脱敏请求内容筛选。 列表只读取摘要投影,查询参数、请求正文、User-Agent 和错误正文按需从详情接口获取,避免每次翻页传输请求快照。
导出通过统一导出中心实体 system.api-access-logs 执行,权限为 system:api-access-log:export。导出重新校验参数与操作者范围,并复用列表的过滤条件。 批量读取以开始时的最大日志 ID 冻结上界,随后按 ID 游标推进,避免导出期间新增记录导致重复、遗漏或无限增长。默认导出元数据,不导出查询或请求正文。
异步写入与可观测性
请求处理完成后,采集记录进入有界的进程内队列,由异步批次写入 api_access_logs,HTTP 请求不等待数据库写入。 队列溢出或落库失败会统计丢弃量,失败告警做频率限制。待写数量、丢弃数量和写入失败次数通过进程监控指标暴露。 正常停机停止接收新日志并排空队列,再关闭数据库连接。
这是一条尽力采集链路:异常退出、强制终止、队列溢出和数据库故障可能损失尚未持久化的访问记录。它不提供业务事务审计或逐条必达保证。
数据保留
api_access_logs 已登记到统一数据保留,默认保留 90 天,按 created_at 清理。 首次注册使用默认值;之后管理员在「系统管理 → 数据保留」调整的启用状态、天数和批大小不会被进程重启覆盖。
data-retention 系统任务默认每日 03:00 顺序执行策略,使用同一 runner 分批删除超期行,记录上次执行时间和删除数量。 该策略采用全局天数;retentionDays = 0 或停用时不自动删除。手动清理复用同一策略,先预览待清理数量,再确认执行。 清理后的明细从列表、详情与后续导出中移除;清理不可恢复,不会自动归档到其他存储。
源日志保留期与导出文件保留期分别管理:API 访问日志默认为 90 天,导出中心生成的普通文件默认保留 7 天,敏感或原始模式文件为 3 天。
实现位置
| 层 | 位置 |
|---|---|
| 持久化 | packages/server/src/db/schema/logs.ts |
| 采集与缓冲 | packages/server/src/middleware/api-access-log.ts、packages/server/src/lib/api-access-log.ts |
| 查询服务与路由 | packages/server/src/services/platform/api-access-logs.service.ts、packages/server/src/routes/platform/api-access-logs.ts |
| 导出与保留 | packages/server/src/services/platform/exports/api-access-logs.ts、packages/server/src/lib/retention/policies.ts |
| 页面与数据访问 | packages/web/src/pages/system/api-access-logs/、packages/web/src/hooks/queries/api-access-logs.ts |