2026-05-18 13:12:51 +08:00
|
|
|
|
# Seq 日志集成
|
|
|
|
|
|
|
2026-07-13 07:45:51 +08:00
|
|
|
|
HoTime 框架内置 Seq 日志推送支持。通过在 `config.json` 填写 `seqUrl` 即可激活。
|
|
|
|
|
|
**目标:用 Seq 集中检索替代翻 `logs/*.txt`**;本地 `logFile` 可并行保留。
|
2026-05-18 13:12:51 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 配置项
|
|
|
|
|
|
|
|
|
|
|
|
在 `config.json` 中添加:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
"seqUrl": "http://127.0.0.1:5341",
|
|
|
|
|
|
"seqApiKey": ""
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 默认值 | 说明 |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| `seqUrl` | 空(不激活) | Seq 服务地址,空值时功能静默不生效 |
|
|
|
|
|
|
| `seqApiKey` | 空 | API Key,免费单用户版留空 |
|
|
|
|
|
|
|
|
|
|
|
|
`instance` 字段由框架自动拼接为 `ip:port`(如 `192.168.1.10:8085`),无需手动填写,同机多进程靠端口区分,跨服务器靠 IP 区分,支持未来集群扩展。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 架构原理
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
业务代码
|
|
|
|
|
|
│ l.Info().Msg("...") ← HoTime Logger 正常调用路径
|
|
|
|
|
|
│ fmt.Println("...") ← 被 redirectStdout 捕获后转入同一路径
|
|
|
|
|
|
↓
|
|
|
|
|
|
multiWriter(hotimev1.5/log/logger.go)
|
|
|
|
|
|
├─ ConsoleWriter → 彩色终端输出(不变)
|
|
|
|
|
|
├─ FileWriter → 本地日志文件(按需,logFile 配置)
|
|
|
|
|
|
└─ SeqWriter
|
|
|
|
|
|
│ Write() 只做 channel <- bytes,O(1) 非阻塞
|
|
|
|
|
|
↓
|
|
|
|
|
|
channel(容量 10000)
|
|
|
|
|
|
↓ 后台 goroutine
|
|
|
|
|
|
批量打包(100 条 或 500ms)
|
|
|
|
|
|
↓ HTTP POST
|
|
|
|
|
|
Seq 服务(CLEF 格式)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**关键特性:**
|
|
|
|
|
|
- `SeqWriter.Write()` 仅向 channel 投递字节即返回,**绝不阻塞** web 请求处理 goroutine
|
|
|
|
|
|
- channel 满时(Seq 宕机/网络故障)新日志被丢弃并计数,主服务完全不受影响
|
|
|
|
|
|
- HTTP POST 设 5s 超时,失败仅打印到 stderr
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 字段映射(zerolog → CLEF)
|
|
|
|
|
|
|
|
|
|
|
|
| zerolog 字段 | Seq CLEF 字段 | 说明 |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| `time` | `@t` | 时间,自动转 ISO 8601 格式 |
|
|
|
|
|
|
| `level` | `@l` | 级别,映射为 Debug/Information/Warning/Error/Fatal |
|
|
|
|
|
|
| `message` / `msg` | `@mt` | 消息正文 |
|
|
|
|
|
|
| `caller` | `caller` | 调用位置,原样保留 |
|
|
|
|
|
|
| 其余自定义字段 | 原字段名 | 原样保留,可在 Seq 中直接查询 |
|
|
|
|
|
|
| — | `instance` | 框架自动注入,值为 `port` 配置(如 `"8085"`) |
|
|
|
|
|
|
| — | `source` | fmt.Println 等捕获的输出标记为 `stdout` |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 单机多进程实例区分
|
|
|
|
|
|
|
|
|
|
|
|
框架启动时自动获取本机出口 IP,拼接为 `ip:port` 格式作为 `instance`:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
单机多进程:
|
|
|
|
|
|
192.168.1.10:8085 ─┐
|
|
|
|
|
|
192.168.1.10:8086 ─┼─ HTTP CLEF ──→ Seq
|
|
|
|
|
|
192.168.1.10:8087 ─┘
|
|
|
|
|
|
|
|
|
|
|
|
多服务器集群:
|
|
|
|
|
|
192.168.1.10:8085 ─┐
|
|
|
|
|
|
192.168.1.11:8085 ─┼─ HTTP CLEF ──→ Seq(中央日志服务器)
|
|
|
|
|
|
192.168.1.12:8085 ─┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Seq 中按实例筛选:
|
|
|
|
|
|
- 单台机器所有进程:`instance like '192.168.1.10%'`
|
|
|
|
|
|
- 精确到某个进程:`instance = '192.168.1.10:8085'`
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-07-13 07:45:51 +08:00
|
|
|
|
## stdout / stderr 全量捕获
|
2026-05-18 13:12:51 +08:00
|
|
|
|
|
2026-07-13 07:45:51 +08:00
|
|
|
|
`SetConfig()` 中自动 `redirectStdout` + `redirectStderr`,并桥接 **logrus**(微信 SDK)到同一管道。
|
2026-05-18 13:12:51 +08:00
|
|
|
|
|
2026-07-13 07:45:51 +08:00
|
|
|
|
| 写法 | Seq 字段 | 说明 |
|
|
|
|
|
|
|------|----------|------|
|
|
|
|
|
|
| `fmt.Println` / `log.Println` | `source=stdout` | **不受 `logLevel` 影响**,`logLevel=0` 也会进 Seq |
|
|
|
|
|
|
| 写 `os.Stderr` 的包 | `source=stderr` | 同上,Error 级别 |
|
|
|
|
|
|
| `logrus.Info`(wechat) | `source=stdout` | redirect 后 `logrus.SetOutput` 桥接 |
|
|
|
|
|
|
| `that.Log.Info/Error...` | 结构化字段 | 经 `multiWriter` → SeqWriter |
|
|
|
|
|
|
| MySQL driver 内部错误 | `source=mysql-driver` | `SetLogger` 适配器 |
|
|
|
|
|
|
| 框架 `recover` 到的 panic | `source=panic` + `stack` | 代码层原因与调用栈 |
|
|
|
|
|
|
|
|
|
|
|
|
单行日志上限约 **10MB**(适配 `GetReqMap` 打整包 body);超长会截断并标注 `...(truncated)`。
|
|
|
|
|
|
|
|
|
|
|
|
**已知不进 Seq(文档边界):**
|
|
|
|
|
|
|
|
|
|
|
|
- 未 `recover`、进程直接崩溃的 runtime 栈(写 fd2,未做 Dup2)
|
|
|
|
|
|
- 达梦驱动自有文件日志(vendor 独立写盘)
|
|
|
|
|
|
- `seqUrl` 挂上之前的极早期引导日志
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 捕获矩阵速查
|
|
|
|
|
|
|
|
|
|
|
|
| 来源 | 进 Seq? | 检索示例 |
|
|
|
|
|
|
|------|----------|----------|
|
|
|
|
|
|
| `that.Log.*` | 是 | `@mt like '%关键词%'` |
|
|
|
|
|
|
| `log.Println` / `fmt.Println` | 是 | `source = 'stdout'` |
|
|
|
|
|
|
| logrus / 标准 `log` | 是 | `source = 'stdout'` |
|
|
|
|
|
|
| stderr 重定向 | 是 | `source = 'stderr'` |
|
|
|
|
|
|
| recover panic | 是 | `source = 'panic'` |
|
|
|
|
|
|
| MySQL driver | 是 | `source = 'mysql-driver'` |
|
|
|
|
|
|
| 队列满丢弃 | 否(计数) | 终端可见 `[seq] queue full` |
|
2026-05-18 13:12:51 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Seq 安装
|
|
|
|
|
|
|
|
|
|
|
|
Seq 提供 Windows MSI 安装包和 Docker 镜像,单机免费,无外部数据库依赖:
|
|
|
|
|
|
|
|
|
|
|
|
- Windows:[https://datalust.co/download/seq](https://datalust.co/download/seq),安装后自动注册为 Windows 服务
|
|
|
|
|
|
- Docker:`docker run -d --restart always --name seq -p 5341:80 -e ACCEPT_EULA=Y datalust/seq`
|
|
|
|
|
|
- 访问 `http://localhost:5341` 使用 Web UI
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 搜索语法速查
|
|
|
|
|
|
|
|
|
|
|
|
| 目标 | 查询语句 |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| 关键词搜索 | 直接输入,如 `支付失败` |
|
|
|
|
|
|
| 日志级别 | `@l = 'Error'` |
|
|
|
|
|
|
| 特定实例 | `instance = '8085'` |
|
|
|
|
|
|
| stdout 来源 | `source = 'stdout'` |
|
2026-07-13 07:45:51 +08:00
|
|
|
|
| panic 恢复 | `source = 'panic'` |
|
|
|
|
|
|
| 请求体调试 | `请求参数GetReqMap` 或 `source = 'stdout'` |
|
2026-05-18 13:12:51 +08:00
|
|
|
|
| 调用位置 | `caller like '%order.go%'` |
|
|
|
|
|
|
| 组合查询 | `@l = 'Error' and instance = '8086' and @mt like '%超时%'` |
|
|
|
|
|
|
| 日期范围 | 右上角时间选择器,支持精确到秒 |
|
2026-07-13 07:45:51 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 相关文档
|
|
|
|
|
|
|
|
|
|
|
|
- [QuickStart_快速上手.md](QuickStart_快速上手.md) — 其中的 `that.Log` 是业务 logs 表,与本文 Seq 推送不同
|
|
|
|
|
|
- [GracefulShutdown_优雅停机.md](GracefulShutdown_优雅停机.md)
|
|
|
|
|
|
- [文档索引](README.md)
|