# Seq 日志集成 HoTime 框架内置 Seq 日志推送支持。通过在 `config.json` 填写 `seqUrl` 即可激活。 **目标:用 Seq 集中检索替代翻 `logs/*.txt`**;本地 `logFile` 可并行保留。 --- ## 配置项 在 `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'` --- ## stdout / stderr 全量捕获 `SetConfig()` 中自动 `redirectStdout` + `redirectStderr`,并桥接 **logrus**(微信 SDK)到同一管道。 | 写法 | 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` | --- ## 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'` | | panic 恢复 | `source = 'panic'` | | 请求体调试 | `请求参数GetReqMap` 或 `source = 'stdout'` | | 调用位置 | `caller like '%order.go%'` | | 组合查询 | `@l = 'Error' and instance = '8086' and @mt like '%超时%'` | | 日期范围 | 右上角时间选择器,支持精确到秒 | --- ## 相关文档 - [QuickStart_快速上手.md](QuickStart_快速上手.md) — 其中的 `that.Log` 是业务 logs 表,与本文 Seq 推送不同 - [GracefulShutdown_优雅停机.md](GracefulShutdown_优雅停机.md) - [文档索引](README.md)