更新记录
1.0.0(2026-11-10)
首个版本。
- 提供 report / query / detail / stats / clean 五个 action
- traceId 自动生成与透传,异常自动记 error 后原样抛出
- 字段名与值级双层脱敏
- 自带日志查询页
平台兼容性
云端兼容性
| 支付宝云 | 腾讯云 | 阿里云 |
|---|---|---|
| × | √ | √ |
云函数日志追踪(traceId)
一个零第三方依赖的 uniCloud 日志云函数。业务云函数只要包一层,就自动获得链路 ID 透传、结构化落库、异常自动捕获、敏感字段脱敏、按链路查询与统计、过期清理,并附一个开箱即用的查询页。
适合:云函数排障靠 console.log 翻日志、多函数串调用串不起链路、线上报错要靠用户描述复现、需要按 traceId 一次性拉出全链路记录的项目。
特性
- traceId 全链路透传:客户端 / 上游传入则复用,没有就自动生成;下游调用自动带
__traceId,下游用wrap()包一层就能复用同一个 ID - 结构化落库:固定字段(时间、级别、服务、动作、耗时、错误码、内容、扩展字段、用户、IP),便于检索统计
- 异常自动捕获:
wrap()包住业务 handler,抛错自动记为error并记堆栈,然后原样抛出,不改变业务语义 - 双层脱敏:SDK 本地先脱敏,云函数服务端再脱敏一次(不信任客户端);字段名匹配之外还有一层值级兜底(手机号、身份证号、JWT)
- 采样与容量控制:日志级别、采样率、单批上限、字符串 / 数组 / 递归深度上限,全部可配
- 日志失败不影响业务:上报是独立云函数调用,所有异常静默吞掉,并有超时保护(默认 1 秒),不会把业务接口拖住
- 零依赖:只用
uniCloud.database()、callFunction()、getClientInfos(),不引任何 npm 包或扩展库 - 自带查询页:按 traceId / 级别 / 时间查询、详情查看、分页、分级别统计
目录结构
uni_modules/aliang-trace-log/
├── package.json 插件配置(含价格与加密文件清单)
├── pages_init.json 自动注册查询页
├── readme.md / changelog.md / license.md
├── uniCloud/
│ ├── cloudfunctions/aliang-trace-log/
│ │ ├── index.js 加密云函数(单文件,含配置/脱敏/存储/查询/入口 5 个分区)
│ │ └── package.json
│ └── database/trace_logs.schema.json 日志集合 Schema
├── js_sdk/trace-client.js 轻量接入 SDK(客户端与云函数两端通用)
└── pages/trace-log/list.vue 查询页
插件内的
uniCloud目录不带-aliyun/-tcb后缀,导入工程后 HBuilderX 会虚拟合并到项目根目录的 uniCloud 中。云函数刻意做成单文件:普通授权版的加密清单是按文件配置的,多文件结构一旦漏配某个 lib 文件,那个文件就会明文留在你的项目里,而且不会有任何报错。单文件可以让加密清单只有一项,不可能漏。
五分钟接入
- 从插件市场导入本插件到 uni-app 项目。
- 上传
uniCloud/database/trace_logs.schema.json到你的服务空间(生成trace_logs集合)。 - 右键
uniCloud/cloudfunctions/aliang-trace-log→ 上传部署。 - 在业务侧接 SDK(见下),或直接在查询页点几下验证。
pages_init.json会自动提示把「日志追踪」页注册进pages.json,确认即可。
建议第 0 步就把
TRACE_QUERY_TOKEN配上(服务空间 → 环境变量)。没配的话,clean会直接拒绝执行,query/stats则对任何知道云函数名的人开放。
接入方式 A:包装业务云函数(推荐)
把 js_sdk/trace-client.js 复制到你自己的云函数目录,然后:
const TraceLog = require('./trace-client.js')
async function business(event, context) {
// 原来的业务代码,一行都不用改
return { errCode: 0, errMsg: 'ok', data: { id: 1 } }
}
exports.main = TraceLog.wrap(business, { service: 'order-service' })
wrap() 自动完成:生成/复用 traceId、计时、捕获异常并记 error、业务返回 errCode != 0 记 warn、采集真实客户端 IP、上报日志。上报失败静默忽略,且最多等 1 秒(timeout 可调)。
串起下游链路(下游同样用 wrap 就会自动复用同一个 traceId):
const res = await TraceLog.callFunction('inventory-deduct', { sku: 'A01', qty: 1 })
接入方式 B:客户端 SDK
import TraceLog from '@/uni_modules/aliang-trace-log/js_sdk/trace-client.js'
TraceLog.configure({ service: 'app-client', sampleRate: 1 })
// 包装调用,自动带 traceId 并记录耗时 / 错误
const res = await TraceLog.callFunction('order-create', { goodsId: 9 })
// 任意自定义日志
TraceLog.report({ level: 'info', action: 'page-view', message: '进入详情页' })
手动上报(不装 SDK 也能用)
await uniCloud.callFunction({
name: 'aliang-trace-log',
data: {
action: 'report',
records: [{
traceId: 'm8x2k1-a3b4c5d6',
level: 'error',
service: 'pay-service',
action: 'charge',
duration: 128,
code: 'PAY_TIMEOUT',
message: '支付网关超时',
extra: { orderNo: 'NO20261110001', retry: 2 },
userId: 'u_10086'
}]
}
})
单条也可以平铺(不用 records):{ action:'report', level:'error', message:'...' },其中 __traceId 也会被当作链路 ID 使用。
API 参考
统一返回 { errCode: 0 | 字符串, errMsg, data }。失败时错误码以 aliang-trace-log- 开头:
| errCode | 含义 |
|---|---|
aliang-trace-log-unauthorized |
令牌不对 |
aliang-trace-log-token-required |
clean 没配 TRACE_QUERY_TOKEN |
aliang-trace-log-invalid-param |
时间参数无法解析 |
aliang-trace-log-invalid-action |
action 不认识 |
aliang-trace-log-collection-missing |
集合不存在(没上传 schema) |
aliang-trace-log-internal |
其他异常 |
| action | 说明 | 主要参数 | 需要 token |
|---|---|---|---|
report |
上报日志 | records(数组,单批默认上限 50,超出部分截断并在 truncated 回报)或平铺单条 |
否 |
query |
分页查询 | traceId level service code userId startTime endTime page pageSize |
是(若配置) |
detail |
按 _id 查详情 |
id |
是(若配置) |
stats |
分级别计数 | traceId service code userId startTime endTime |
是(若配置) |
clean |
清理过期日志 | days(默认取 TRACE_RETENTION_DAYS,30 天) |
必须 |
report 单条记录字段:traceId / spanId / level / service / action / duration / code / message / extra / userId / clientIp。
report 的返回:{ accepted, dropped, truncated, insert }。insert.degraded 为 true 表示批量写入失败后改成了逐条写,insert.skipped 是没能写进去的条数。
时间参数必须是毫秒时间戳(Date.now()),也接受能 Date.parse 的字符串(如 '2026-11-01')。传了别的东西会直接返回 invalid-param,不会静默忽略条件。
查询示例:
const res = await uniCloud.callFunction({
name: 'aliang-trace-log',
data: {
action: 'query',
traceId: 'm8x2k1-a3b4c5d6',
level: 'error',
startTime: Date.now() - 86400000,
page: 1, pageSize: 20,
token: '你的查询令牌'
}
})
console.log(res.result.data.list)
配置项
在 uniCloud 服务空间的环境变量里配置。collection 与 queryToken 只能用环境变量设置,data.config 无法覆盖;其余可按次覆盖。
| 环境变量 | 默认 | 说明 |
|---|---|---|
TRACE_COLLECTION |
trace_logs |
日志集合名。不接受请求侧覆盖,否则调用方能把 clean/query 指向任意业务集合 |
TRACE_LEVEL |
info |
最低记录级别:debug / info / warn / error |
TRACE_SAMPLE_RATE |
1 |
采样率 0~1;error 始终全量记录 |
TRACE_QUERY_TOKEN |
空 | 查询/清理令牌。只能通过环境变量设置;clean 没它直接拒绝 |
TRACE_RETENTION_DAYS |
30 |
clean 默认保留天数 |
TRACE_MAX_BATCH |
50 |
单批最多写入条数 |
TRACE_MAX_STRING |
2000 |
单字符串截断长度 |
TRACE_MAX_EXTRA |
8000 |
extra 序列化上限,超出时按 key 逐个保留并标记 _truncated |
TRACE_MAX_ARRAY |
20 |
数组保留元素数 |
TRACE_MAX_DEPTH |
4 |
对象递归深度 |
TRACE_REDACT_VALUES |
1 |
值级脱敏开关(手机号 / 身份证号 / JWT),设 0 关闭 |
安全设计:
TRACE_QUERY_TOKEN与TRACE_COLLECTION都刻意不接受data.config覆盖。前者防止调用方自己指定 token 绕过鉴权,后者防止调用方把破坏性的clean指向业务集合。
data.config 可覆盖其余参数,也可追加 sensitiveKeys(数组)扩充脱敏字段名。
安全与隐私
- 字段名脱敏(子串匹配,大小写不敏感,支持中文键名):password / passwd / pwd / secret / token / authorization / cookie / session / apikey / privatekey / credential / idcard / identity / phone / mobile / email / bankcard / cardno / cvv / signature / 手机号 / 身份证 / 姓名 / 住址 / 地址 / 病历号 / 住院号。命中值替换为
[REDACTED]。 - 值级兜底脱敏:
message正文和extra的字符串值里出现的 11 位手机号、18 位身份证号、JWT 会被替换为[PHONE]/[IDCARD]/[JWT]。字段名匹配管不到正文,所以需要这一层。 - 服务端再次脱敏,客户端 SDK 处理与否都不影响结果。
- 集合
permission全部为false,前端无法直连,只能通过云函数访问。 - 数据全部写在你自己的服务空间,不向任何第三方服务器发送。
- 请自行避免上报患者身份信息、身份证号等敏感个人信息;本插件的脱敏是兜底,不是合规豁免。
clean默认 fail-closed:没配TRACE_QUERY_TOKEN时一律拒绝,避免"装完就默认允许删库"。- 建议给
query/detail/stats也配上 token,并把查询页入口放在管理后台。
容量估算(重要)
默认 sampleRate: 1,也就是每个被 wrap() 包住的请求都会写一条日志。按 10 万请求/天算就是 10 万条/天、约 300 万条/月,会实实在在吃掉你服务空间的存储和数据库读写额度。
三个建议:
- 生产环境把
TRACE_SAMPLE_RATE调到0.1(错误日志不受影响,始终全量); - 给
trace_logs配定时清理(见下); - 只把需要排障的关键云函数用
wrap()包起来,不要全站无脑包。
索引建议
Schema 未强制声明索引(避免不同云厂商差异)。日志量上来后,建议在 uniCloud 控制台为 trace_logs 建:
| 索引字段 | 用途 |
|---|---|
trace_id |
按链路拉全量 |
create_time(降序) |
列表分页与时间范围 |
level + create_time |
错误筛选 |
code |
错误码聚合 |
提醒:这份 Schema 的作用是创建集合 + 在控制台声明字段。uniCloud 的 DB Schema 只在 JQL 下生效,云函数走的是原生数据库接口,所以
required、bsonType这些不对云函数写入做校验,字段规范由云函数自己保证。另外create_time存的是毫秒时间戳数字,不是日期类型。
定时清理
clean 需要 token,定时触发可以在触发器参数里带上:
{ "action": "clean", "days": 30, "token": "与环境变量 TRACE_QUERY_TOKEN 相同的值" }
这样既能自动清理,又不会出现"任何人都能调 clean 删日志"的口子。
常见问题
Q:报 collection-missing。
A:日志集合不存在。上传插件自带的 uniCloud/database/trace_logs.schema.json 到服务空间后重试。
Q:调用正常但查不到日志。
A:依次检查:云函数是否上传部署、集合是否创建、TRACE_LEVEL 是否高于上报级别、TRACE_SAMPLE_RATE 是否小于 1、业务侧是否 await 了包装后的 handler。
Q:报 token-required。
A:在调 clean,但服务空间没配 TRACE_QUERY_TOKEN。这是刻意的:清理是破坏性操作,不允许在"未配置即开放"的默认状态下被执行。
Q:报 invalid-param。
A:startTime / endTime 传了无法解析的值。请传毫秒时间戳。
Q:云函数里日志偶尔丢。
A:SDK 默认等待上报完成(推荐),且有 1 秒超时保护。若手动设了 fireAndForget: true,serverless 实例在请求返回后可能冻结,异步请求发不出去,云函数环境请保持默认。
Q:报 unauthorized。
A:服务空间配了 TRACE_QUERY_TOKEN,但请求没带 token,或值不一致。查询页在筛选区下方会出现令牌输入框(输入后会记住)。
Q:云函数报模块找不到。
A:云函数是单文件,理论上不会有子模块缺失。请确认上传的是整个 aliang-trace-log 云函数目录,且 index.js 没有被截断。
Q:支持 uni-app x / 鸿蒙 / 小程序吗?
A:云函数与 js_sdk/trace-client.js 均为纯 JS,各端可用;自带查询页是 vue 页面,仅用于 uni-app 项目(uni-app x 项目可只接 SDK,用 callFunction 自行取数)。
授权方式(购买前请先读)
- 付费普通授权版按服务空间 spaceId 绑定。开发空间和生产空间是两个 spaceId,需要各自授权。
- 提供 7 天试用,试用期内可以把加密云函数部署到指定服务空间体验;试用到期后,加密云函数会被平台自动删除。
- 加密云函数无法上传到你未授权的其他服务空间。
版本要求
- HBuilderX 4.71+(平台兼容性使用新规范),uniCloud 阿里云 / 腾讯云服务空间
- JavaScript 普通云函数(CommonJS),不需要任何扩展库
授权
购买后按 DCloud 插件市场的标准授权条款使用,可用于自己的任意商业项目,项目数量不限。普通授权版不含源码,请勿反编译或二次分发。

收藏人数:
购买源码授权版(
导入插件并试用
赞赏(1)
下载 0
赞赏 1
下载 35291
赞赏 159
赞赏
京公网安备:11010802035340号