Winston + highlight.io 日志接入实战:用 HTTP Transport 将 Node.js JSON 日志送入全栈监控平台
Winston + highlight.io 日志接入实战:用 HTTP Transport 将 Node.js JSON 日志送入全栈监控平台
导读
本篇指南讲解如何在 Node.js 服务中使用 Winston 日志框架接入 highlight.io 的日志摄取能力:借助 Winston 内置的 Http Transport,将应用日志以 JSON 形式实时上报到 highlight.io 云端,与前端会话回放、错误监控打通,形成全栈可观测闭环。读完本文,你将掌握完整的 Winston 接入配置、请求头与路径语义、日志验证方法,并理解 highlight.io 服务端 /v1/logs/json 端点的底层实现,让日志从"本地可见"升级为"平台可查、可检索、可关联"。
1. 接入前的准备:前置依赖
在配置 Winston Transport 之前,请先确认两件事:
-
前端集成(可选但推荐):如果你正在为应用接入 highlight.io 前端 SDK,请先按 前端快速开始 完成初始化,并参考前后端关联映射指南,让后端日志能与前端会话正确关联。这一步不强制,但能显著提升全栈排查效率。
-
获取项目 ID:登录 highlight.io 控制台,在项目设置中找到你的
Project ID。它将被填入 HTTP 请求头的x-highlight-project字段中,用于日志归属识别。
2. 核心配置:创建 Winston HTTP Transport
Winston 自带 transports.Http,可将日志序列化后通过 HTTP 上报。highlight.io 官方 Quick Start(定义于 winston.tsx)给出了如下开箱即用的配置:
import {createLogger, format, transports} from 'winston';
const highlightTransport = new transports.Http({
host: 'pub.highlight.run',
path: "/v1/logs/json",
ssl: true,
headers: {
'x-highlight-project': '<YOUR_PROJECT_ID>',
'x-highlight-service': 'EXAMPLE_NODEJS_SERVICE',
},
})
export const logger = createLogger({
level: 'info',
format: format.combine(
format.json(),
format.errors({ stack: true }),
format.timestamp(),
format.prettyPrint(),
),
transports: [new transports.Console(), highlightTransport],
})
配置项逐项拆解
| 配置项 | 取值 | 含义 |
|---|---|---|
host |
pub.highlight.run |
highlight.io 公有云日志摄取域名,对应生产环境入口 |
path |
/v1/logs/json |
JSON 日志接收端点,服务端由 HandleJSONLog 处理器承载(见下文源码) |
ssl |
true |
使用 HTTPS 加密传输,生产环境必须开启 |
headers['x-highlight-project'] |
<YOUR_PROJECT_ID> |
必填,标识日志归属的项目 |
headers['x-highlight-service'] |
你的服务名 | 建议填写,便于按服务维度过滤日志 |
几点实战建议:
- 替换占位符:将
<YOUR_PROJECT_ID>替换为真实项目 ID,将EXAMPLE_NODEJS_SERVICE替换为你的服务名(如order-service),否则日志会被归到错误的项目或显示为默认服务名。 - 日志级别:
level: 'info'意味着info及以上级别(warn、error)都会进入 Transport 管道;若只关心错误,可调整为error。 - Format 组合:
format.json()保证日志被序列化为 JSON 载荷;format.errors({ stack: true })会将 Error 对象展开并附带堆栈;format.timestamp()为每条日志注入时间戳;format.prettyPrint()则便于本地控制台阅读。生产环境中也可按需去掉prettyPrint以降低本地输出噪音。 - 双 Transport 并存:
Console与highlightTransport同时挂载,意味着日志"本地照常打印、远端同步上报",无需改动任何业务代码中的logger.info/error调用点。
3. 底层原理:/v1/logs/json 端点是如何处理日志的
配置中的 path: "/v1/logs/json" 并非虚构地址,它在 highlight.io 后端有真实实现。查看 backend/http/logging.go 中的路由注册:
func Listen(r *chi.Mux, t trace.Tracer) {
tracer = t
r.Route("/v1", func(r chi.Router) {
r.Use(highlightChi.Middleware)
r.HandleFunc("/logs/raw", HandleRawLog)
r.HandleFunc("/logs/json", HandleJSONLog)
r.HandleFunc("/logs/firehose", HandleFirehoseLog)
})
}
可以看到,/v1 路由族同时暴露了三种日志摄取入口:
/logs/json:接收 结构化 JSON 日志(即本指南 Winston 所用的端点),支持批量数组与 NDJSON 流式体;/logs/raw:接收纯文本原始日志,日志内容即请求体,级别默认记为info(见 HandleRawLog);/logs/firehose:面向 AWS Firehose 等流式管道的高吞吐入口。
HandleJSONLog 在解析请求时会读取 x-highlight-project 等头部与 project、service 查询参数,将 JSON 中的每条日志转换为内部 hlog.Log 结构,补齐 service.name 等 OpenTelemetry 语义属性后,通过 SubmitHTTPLog 交给下游(ClickHouse)存储。这正是"Winston 上报 → 服务端规范化 → 可检索存储"的完整链路。
值得注意:Winston HTTP Transport 默认会将每条日志作为独立 JSON 对象 POST 上去,而 HandleJSONLog 同样支持 NDJSON(多行 JSON)批量体。若你的应用日志吞吐量很大,可以考虑使用自定义 transport 做本地批量缓冲,减少 HTTP 请求次数(从源码结构与端点设计看,服务端已为批量场景做了支持)。
4. 验证日志是否成功上报
完成配置后,用以下方法验证链路是否打通(对应 Quick Start 中的 verifyLogs 步骤):
- 在业务代码中主动输出一条日志,例如
logger.info('Hello from my Node.js service'); - 启动服务,确认控制台正常打印(Console Transport 生效);
- 登录 highlight.io 控制台,进入 Logs 日志检索页面,选择对应的项目;
- 按服务名
EXAMPLE_NODEJS_SERVICE(或你填写的服务名)过滤,应能看到刚输出的日志记录,包含时间戳、级别与完整 JSON 载荷。
如果日志迟迟未出现,按以下顺序排查:
- 项目 ID 是否填写正确(
x-highlight-project与查询参数project二选一即可,但 header 方式是 Winston 配置的标准做法); - 网络是否可达
pub.highlight.run(公网域名,防火墙/代理需放行 443 端口); - 日志级别是否低于
level: 'info'而被过滤; - 查看服务端端点测试样例,确认请求格式与预期一致——仓库测试 backend/http/logging_test.go 展示了
POST /v1/logs/json的多种合法请求体(单条 NDJSON、批量 JSON 数组、带project/service查询参数等),可作为对照参考。
5. 进阶:与其他日志摄取方式对比
highlight.io 不止支持 Winston,同一套平台还提供多种摄取路径,便于按场景选型:
| 方式 | 适用场景 | 特点 |
|---|---|---|
| Winston HTTP Transport(本文) | Node.js + Winston 栈 | 零额外依赖,仅用 Winston 内置能力,配置即用 |
| Pino Transport | 追求极致性能的 Node.js 服务 | 与 Pino 的 JSON 序列化原生契合 |
| OTLP 协议 | 已采用 OpenTelemetry 的异构系统 | 标准协议,多语言 SDK 通用,便于与 traces/metrics 统一出口 |
/v1/logs/raw 原始端点 |
快速验证、脚本化上报 | 请求体即消息文本,无需构造 JSON |
若你的服务已在使用 OpenTelemetry,也可直接用 OTLP 上报而跳过 Winston Transport,两种方式在 highlight.io 的 Logs 视图中统一展示。
6. 小结
本文围绕 Winston 与 highlight.io 的集成,完整覆盖了从 HTTP Transport 配置、请求头与路径语义、日志验证到底层端点实现的全部要点:
- 用
transports.Http+pub.highlight.run+/v1/logs/json即可完成接入,核心代码不超过 20 行; x-highlight-project与x-highlight-service两个请求头承担了项目归属与服务标识的关键职责;- 后端 backend/http/logging.go 的
/v1路由族提供了 JSON、Raw、Firehose 三种摄取入口,测试用例(logging_test.go)可帮助你验证请求格式; - 完成上报后,前端会话回放、错误监控与后端日志可在同一平台统一检索,真正实现全栈可观测。
现在,替换占位符、启动服务,去 Logs 页面看看你的第一条 Winston 日志吧。