日志插件
logs 插件从设备采集结构化日志行,在服务端持久化存储,并通过 Server-Sent Events(SSE)实时推流。日志支持按时间范围、来源和严重级别查询,并提供可按租户配置的保留策略。
概览
| 属性 | 值 |
|---|---|
| 插件 ID | logs |
| 类型 | SDK(pluginsdk.BackendPlugin) |
| 版本 | 2.0.0 |
| HTTP 路由 | 是——查询 + SSE 实时流 |
| Prometheus 指标 | 无 |
| 总线订阅 | evt.logs.v1.* |
| 数据库架构 | 是——按后端存储日志行表 |
HTTP 路由
所有路由挂载于 /api/v1/plugins/logs/,经过标准中间件栈处理:
频率限制 → JWT 认证 → 租户认证 → 按路由 RBAC 检查
| 方法 | 路径 | 所需权限 | 说明 |
|---|---|---|---|
GET | /api/v1/plugins/logs/lines/{device_id} | logs/stream:read | 查询历史日志行 |
GET | /api/v1/plugins/logs/tail/{device_id} | logs/stream:read | 通过 SSE 流式推送新日志行 |
查询日志行(GET /lines/{device_id})
返回指定设备的历史日志行分页列表。
查询参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
source | string | — | 按日志来源过滤(如 syslog、app) |
level | string | — | 按严重级别过滤:debug、info、warn、error |
limit | int | 200 | 最大返回行数 |
since | RFC 3339 | — | 返回该时间戳之后(含)的日志行 |
until | RFC 3339 | — | 返回该时间戳之前(含)的日志行 |
请求示例:
http
GET /api/v1/plugins/logs/lines/550e8400-e29b-41d4-a716-446655440000
?level=error&since=2025-03-25T00:00:00Z&limit=50
Authorization: Bearer <token>
X-Tenant-ID: <tenant-id>响应(JSON 数组):
json
[
{
"tenant_id": "660f9511-...",
"device_id": "550e8400-...",
"source": "syslog",
"level": "error",
"message": "Out of disk space on /dev/sda1",
"logged_at": "2025-03-25T10:42:00Z"
}
]日志实时流(GET /tail/{device_id})
建立长连接 Server-Sent Events 流,实时推送新日志行。适用于类 tail -f 的实时 UI 场景。
请求:
http
GET /api/v1/plugins/logs/tail/550e8400-e29b-41d4-a716-446655440000
Authorization: Bearer <token>
X-Tenant-ID: <tenant-id>
Accept: text/event-stream响应头:
http
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-aliveSSE 事件类型:
| 事件类型 | 发送时机 | 数据格式 |
|---|---|---|
connected | 连接成功时 | {"device_id": "..."} |
log | 每条新日志行 | JSON 日志行对象(与查询响应格式相同) |
SSE 流示例:
event: connected
data: {"device_id":"550e8400-e29b-41d4-a716-446655440000"}
event: log
data: {"tenant_id":"660f9511-...","device_id":"550e8400-...","source":"app","level":"info","message":"Service started","logged_at":"2025-03-25T10:43:01Z"}
event: log
data: {"tenant_id":"660f9511-...","device_id":"550e8400-...","source":"syslog","level":"warn","message":"CPU temperature high","logged_at":"2025-03-25T10:43:05Z"}服务端使用内存尾部缓冲区按设备缓存最新日志行,并将其扇出推送给已连接的 SSE 客户端。
RBAC 权限
| 权限 | 默认角色 | 说明 |
|---|---|---|
logs/stream:read | viewer、operator、tenant_admin | 查询日志行及打开实时推流 |
typescript
can(perms, 'logs/stream', 'read') // 显示设备日志面板消息总线
日志插件订阅 evt.logs.v1.*,接收设备代理通过 NATS 桥接转发的日志事件。
每条传入事件将被:
- 持久化到已配置的存储后端。
- 写入内存尾部缓冲区,供实时 SSE 客户端使用。
存储后端
日志插件支持两种可配置存储后端:
| 后端 | 配置值 | 说明 |
|---|---|---|
| PostgreSQL | postgres(默认) | 日志存储于平台数据库,遵循标准租户 RLS |
| Elasticsearch | elasticsearch | 日志存储于外部 Elasticsearch 集群,适用于高容量场景 |
通过插件配置设置后端:
json
{
"backend": "postgres"
}插件配置
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
sources | string | file:/var/log/syslog | 代理采集的日志来源(空格分隔的 URI) |
max_lines_per_sec | int | 100 | 每设备速率限制,防止日志洪泛 |
backend | string | postgres | 存储后端:postgres 或 elasticsearch |
elasticsearch_url | string | — | 当 backend=elasticsearch 时必填 |
配置示例:
json
{
"sources": "file:/var/log/syslog file:/var/log/app.log",
"max_lines_per_sec": 200,
"backend": "postgres"
}日志保留策略
插件每日执行一次保留清理,删除超过租户配置 LogRetentionDays 的日志行。默认保留周期在平台设置中配置,并按租户独立生效。
要为特定租户修改保留策略,通过 UpdateTenant 更新租户设置(需要 tenant_admin 权限):
json
{
"log_retention_days": 30
}设备端插件
设备代理运行对应的 logs 代理插件,负责:
- 读取
sources配置(默认:file:/var/log/syslog)。 - 持续监控已配置的日志文件,解析每行的严重级别和时间戳。
- 将输出行速率限制到
max_lines_per_sec。 - 将批量日志以
evt.logs.v1.lines发布到代理总线,通过 NATS 桥接传输至服务端。 - 接收
cfg.plugins.v1.set消息时热重载配置。