跳到主要内容

服务调用日志

📋 概述

使用云开发的资源(HTTP 访问服务、云函数、数据库、云存储)时,会自动产生对应的服务调用日志,供开发者在云开发控制台进行检索和分析。通过服务调用日志,您可以:

  • 🔍 追踪请求链路 - 完整记录服务调用的全链路信息
  • 📊 性能分析 - 监控各服务的响应时间和性能表现
  • 🐛 问题排查 - 快速定位错误和异常问题
  • 📈 业务洞察 - 分析用户行为和系统使用情况

📝 日志信息

通过 SDK 或者 HTTP 访问服务使用云开发的资源时,会产生一条服务调用日志。每条服务调用日志包含以下核心信息:

信息类别说明用途
📊 日志元数据traceId、spanId、childOf链路追踪和关联分析
🎯 调用服务&事件service、event识别服务类型和操作类型
🗂️ 资源信息function、file_path 等定位具体访问的资源
👤 调用者信息invoker、source、ua、ip识别请求来源和用户
时间信息startTime、timeCost性能分析和时序追踪
错误信息errorCode、errorMsg问题诊断和错误分析

📊 日志元数据

日志元数据是实现分布式链路追踪的核心,包含以下字段:

字段说明示例值
traceId全链路唯一标识符8f431b7e-bfcc-423e-99d8-cda72471ff49
spanId当前调用的唯一标识符bbe75687-fffb-6cb8
childOf父级调用的 spanIdabc12345-defg-6789

🔗 链路追踪原理

在一次完整的服务调用中,可能访问多个云开发资源,产生多条服务调用日志:

  • 🆔 相同 traceId:同一次请求的所有日志共享相同的 traceId
  • 🏷️ 不同 spanId:每个服务调用都有唯一的 spanId
  • 🔗 childOf 关联:记录调用的父子关系,构建完整调用链
📖 调用链示例

场景:通过 SDK 调用云函数 A,云函数 A 调用云函数 B

SDK --> 云函数 A --> 云函数 B

日志记录

  • 日志 A:traceId: abc123, spanId: span001, childOf: null
  • 日志 B:traceId: abc123, spanId: span002, childOf: span001

通过 traceId 可以查询到完整调用链,通过 childOf 可以还原调用关系。

🎯 调用服务&事件

日志中使用 serviceevent 来标记每次服务调用的服务类型和具体操作:

服务类型Service 值Event 事件动作说明
🔧 云函数functioncallFunction函数调用执行
📁 云存储storageuploaddeletedownloadgetTempFileURL文件操作
🗄️ 数据库databaseaddremoveupdategetcountaggregateCRUD 和聚合操作
🌐 云托管appGETPOSTPUTDELETEPATCHHTTP 请求方法

📋 常见事件类型详解

云存储事件:

  • upload - 文件上传
  • delete - 文件删除
  • download - 文件下载
  • getTempFileURL - 获取临时访问链接

数据库事件:

  • add - 新增记录
  • remove - 删除记录
  • update - 更新记录
  • get - 查询记录
  • count - 统计数量
  • aggregate - 聚合查询

云托管事件:

  • HTTP 方法对应具体的 API 调用类型

🗂️ 资源信息

不同的资源类型通过不同的字段来标识具体访问的资源:

资源类型字段名数据类型说明示例
🔧 云函数functionString函数名称"login", "sendEmail"
📁 云存储file_pathArray文件路径列表["/images/avatar.jpg"]
🗄️ 数据库collectionNameArray集合名称列表["users", "orders"]
🌐 HTTP 服务httpPathString请求路径(不含查询参数)"/api/user/profile"

📝 字段说明

file_path 数组格式

  • 单文件操作:["/path/to/file.jpg"]
  • 批量操作:["/file1.jpg", "/file2.png", "/file3.pdf"]
  • 批量获取临时链接时会包含多个文件路径

collectionName 数组格式

  • 单表操作:["users"]
  • 聚合查询:["users", "orders", "products"]
  • 跨集合操作时会包含多个集合名

httpPath 格式

  • 原始请求:GET /api/user/profile?id=123&type=full
  • 记录路径:"/api/user/profile"(自动去除查询参数)

👤 调用者信息

服务调用日志详细记录了请求的来源信息,便于安全审计和问题排查:

字段名说明可能值用途
invoker调用者身份标识adminuid:user123anonymous用户身份识别
source请求来源渠道web-sdknode-sdkhttpschedule来源渠道分析
ua客户端 User-Agent浏览器/SDK 版本信息客户端环境分析
invokerIp请求来源 IP 地址192.168.1.10010.0.0.1地理位置和安全分析

🔍 字段详解

invoker 调用者类型

  • admin - 管理员调用(控制台操作)
  • uid:xxxxx - 已认证用户调用
  • anonymous - 匿名用户调用
  • 空值 - 系统内部调用

source 来源渠道

  • web-sdk - Web 端 SDK 调用
  • node-sdk - Node.js SDK 调用
  • admin-sdk - 管理端 SDK 调用
  • http - 直接 HTTP API 调用
  • schedule - 定时触发器调用
  • trigger - 数据库触发器调用

ua 信息示例

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
CloudBase-JS-SDK/1.5.0
CloudBase-Node-SDK/2.8.1

⏰ 时间信息

时间信息用于性能分析和调用时序追踪:

字段名说明格式示例
startTime服务调用开始时间ISO 8601 时间戳2023-12-01T10:30:45.123Z
timeCost调用耗时(毫秒)数值150(表示 150ms)

📊 性能分析应用

通过时间信息可以进行:

  • 性能监控:识别慢查询和性能瓶颈
  • 📈 趋势分析:统计平均响应时间变化
  • 🚨 异常检测:发现响应时间异常的请求
  • 🎯 优化指导:为性能优化提供数据支撑

❌ 错误信息

错误信息帮助快速定位和诊断问题:

字段名说明示例
errorCode标准错误码INVALID_PARAMPERMISSION_DENIED
errorMsg详细错误描述"参数 userId 不能为空""数据库连接超时"

🔧 常见错误码

错误码说明解决方案
INVALID_PARAM参数错误检查请求参数格式和必填项
PERMISSION_DENIED权限不足检查用户权限和安全规则
RESOURCE_NOT_FOUND资源不存在确认资源路径和名称正确
QUOTA_EXCEEDED配额超限检查资源使用量和配额限制
NETWORK_ERROR网络错误检查网络连接和服务状态

🎯 典型使用场景

🔍 场景一:用户访问报错排查

检索日志方法详情请参见 检索日志

假如用户 A 某次访问云开发的资源报错,那么怎样定位错误原因呢?

  1. 通过 invoker:A and errorCode:* 来检索此用户最新的访问出错的服务调用日志;
  2. 检索到服务调用日志后,根据访问时间查阅到日志的 traceId, 通过 traceId:\${traceId} 来检索此次服务调用的所有服务调用日志,根据日志中的调用信息、资源信息、错误信息来分析出错的原因。
  3. 点击”全链路日志“按钮前往全链路日志页面查看调用链关系。在调用页,可以点击查看函数执行中的日志

🌐 场景二:云托管服务调用场景

用户调用云托管 A 服务的接口 1,云托管 A 接口 1 中再次调用云托管 A 服务的接口 2 时,希望将请求关联上同一个 traceid,则需要业务侧进行配合改造。

  1. /json接口中调用 /trace 接口,headers 里透传请求头中的x-cloudbase-trace字段
  2. /trace接口中,解开x-cloudbase-trace,得到traceId,在日志中输出,并可以在后续的日志搜索时,通过

以 nodejs koa 框架代码为例,云托管 A 中 /json接口中调用另外一个/trace接口

router.get("/json", async (ctx, next) => {
const res = await axios.get(
"https://test-2gbynbtb9996d4d0-1252395194.ap-shanghai.service.tcloudbase.com/node-capp/trace",
{
headers: {
"x-cloudbase-trace": ctx.req.headers["x-cloudbase-trace"]
}
}
);

ctx.body = res.data;
});
router.get("/trace", async (ctx, next) => {
// 从base64转为utf8编码,数据格式为 ${traceId},${spanId},${on | off}
// 例子:OGY0MzFiN2ViZmNjNDIzZTk5ZDhjZGE3MjQ3MWZmNDksYmJlNzU2ODdmZmZiNmNiOCxvbg 解开后为 8f431b7ebfcc423e99d8cda72471ff49,bbe75687fffb6cb8,on
const traceStr = Buffer.from(ctx.req.headers["x-cloudbase-trace"], "base64").toString("utf-8");

const [traceId] = traceStr.split(",");
// 解出后,可以在日志中打印该字段,方便关联上日志
console.log(`${traceId}: traceId log start`);
ctx.body = {
traceStr,
traceId
};
console.log(`${traceId}: traceId end`);
});

注:如果是云函数中调用云托管,x-cloudbase-trace 则是透传云函数环境变量中的 TCB_TRACELOG