背景
为有效监控无服务器架构的业务性能,我们需要将AWS Lambda函数的全链路数据接入观测云进行统一可观测性分析。由于Lambda环境的特殊性,最佳实践是构建一个集成了OpenTelemetry的官方Layer。该Layer能自动捕获函数调用链与性能指标,并通过标准OTLP协议上报。为确保数据传输的高效性与前瞻性,我们特别将社区常见的JSON格式调整为Protobuf编码,以适配观测云后端的技术演进,为函数性能优化与故障诊断提供坚实的数据基础。
前提
运行时:NodeJS 22
安装Datakit并配置采集器
进入观测云控制台-「集成」-「Datakit」-「Linux」复制命令安装Datakit

进入 /usr/local/datakit/conf.d/samples ,将 opentelemetry.conf.sample 复制到上级目录 /conf.d 中,并修改文件后缀为 conf
bash
cp opentelemetry.conf.sample ../opentelemetry.conf
编辑 opentelemetry 配置文件,修改如下部分,添加 enable = true ,然后保存

执行以下命令重启 Datakit
bash
datakit service -R
准备一个lambda函数
以下 demo 脚本调用了一个 Java 服务 52.83.66.70:8090/user:
bash
const http = require('http');
exports.handler = async (event, context) => {
console.log('=== 开始调用Java服务验证TraceID ===');
try {
console.log('准备调用Java服务: 52.83.66.70:8090/user');
// 调用您的Java服务
const javaServiceResult = await callJavaService();
console.log('Java服务调用成功');
return {
statusCode: 200,
body: JSON.stringify({
success: true,
message: 'Java服务调用完成',
javaServiceResponse: javaServiceResult,
requestId: context.awsRequestId,
timestamp: new Date().toISOString()
})
};
} catch (error) {
console.error('调用Java服务失败:', error);
return {
statusCode: 500,
body: JSON.stringify({
success: false,
message: 'Java服务调用失败',
error: error.message
})
};
}
};
function callJavaService() {
return new Promise((resolve, reject) => {
console.log('开始发起HTTP请求到Java服务...');
const options = {
hostname: '52.83.66.70',
port: 8090,
path: '/user',
method: 'GET',
timeout: 5000, // 5秒超时
headers: {
'User-Agent': 'Lambda-OTEL-Test/1.0',
'Accept': 'application/json'
}
};
const req = http.request(options, (res) => {
console.log(Java服务响应状态码: ${res.statusCode});
console.log('响应头:', JSON.stringify(res.headers));
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Java服务响应数据长度:', data.length);
console.log('原始响应:', data);
try {
// 尝试解析JSON响应
const parsedData = data ? JSON.parse(data) : {};
resolve({
statusCode: res.statusCode,
data: parsedData,
headers: res.headers,
rawResponse: data
});
} catch (e) {
// 如果JSON解析失败,返回原始数据
console.log('响应不是JSON格式,返回原始数据');
resolve({
statusCode: res.statusCode,
data: data,
headers: res.headers,
isJson: false
});
}
});
});
req.on('error', (error) => {
console.error('请求Java服务错误:', error.message);
reject(error);
});
req.on('timeout', () => {
console.error('请求Java服务超时');
req.destroy();
reject(new Error('请求Java服务超时'));
});
// 发送请求
req.end();
console.log('HTTP请求已发送到Java服务');
});
}

测试事件:

构建layer
构建官方的layer做导出器,通过 Layer 集成,无侵入式地自动捕获 Lambda 函数执行的链路数据可以自动采集lambda函数的链路数据,将采集的数据转换为 OpenTelemetry(OTel)标准格式,确保与观测后端平台的兼容性。
注意:Node.js 社区提供的默认 OpenTelemetry 导出器通常使用 HTTP/JSON 方式发送数据,需要将默认的导出协议从 HTTP/JSON 改为 HTTP/PROTOBUF,Datakit后续可能考虑废弃HTTP/JSON方式。Protobuf 编码具有更高的序列化/反序列化效率,能显著降低传输数据大小和网络开销,尤其适用于 Lambda 的短时执行环境。
具体可以参考 Opentelemetry 的社区:https://github.com/open-telemetry/opentelemetry-lambda/tree/main/nodejs
克隆仓库
bash
git clone https://github.com/open-telemetry/opentelemetry-lambda
修改协议
进入项目目录,将相关文件的 @opentelemetry/exporter-trace-otlp-http 改成@opentelemetry/exporter-trace-otlp-proto,一共需要修改3个文件。
bash
cd opentelemetry-lambda/nodejs
./packages/layer/src/wrapper.ts

./nodejs/packages/layer/package.json

./nodejs/packages/layer/test/wrapper.spec.ts

安装依赖
bash
npm install
构建项目
bash
npm run build
在./nodejs/packages/layer/build/会有一个layer.zip文件
添加Layer
创建 Layer
在 AWS 控制台 Lambda进入「layer」,新建一个layer,选择上传.zip文件方式上传刚才生成的layer.zip文件,架构选择x86、运行时选择nodejs。创建好后复制ARN

添加 Layer
在 Demo 函数中添加 Layer,选择指定一个 ARN ,将刚才的 ARN 复制进去,点击「添加」

配置环境变量
配置lambda环境变量,选择「配置」-「环境变量」

添加如下变量:
| Key | VALUE |
|---|---|
| AWS_LAMBDA_EXEC_WRAPPER | /opt/otel-handler |
| OTEL_EXPORTER_OTLP_ENDPOINT | http://<datakit主机地址>:9529/otel |
| OTEL_EXPORTER_OTLP_TRACES_PROTOCOL | http/protobuf |
| OTEL_NODE_ENABLED_INSTRUMENTATIONS | aws-lambda,aws-sdk,http,https,pg,mysql,redis |
| OTEL_SERVICE_NAME | 服务名称 |
| OTEL_TRACES_SAMPLER | always_on |
测试函数
回到函数点击测试

观测云效果
链路上报效果如下:



