无服务器计算
本指南展示了如何使用 OpenTelemetry 仪表化库来跟踪无服务器函数。
AWS Lambda
注意
您还可以使用社区提供的 Lambda 层来自动仪表化 AWS Lambda 函数。以下展示了如何使用 OpenTelemetry Lambda 包装器手动仪表化 AWS Lambda 函数并将跟踪发送到配置的后端。
如果您对即插即用的用户体验感兴趣,请参考OpenTelemetry Lambda 层。
依赖项
首先,创建一个空的 package.json 文件:
npm init -y
然后安装所需的依赖项:
npm install \
@opentelemetry/api \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-http \
@opentelemetry/instrumentation \
@opentelemetry/sdk-trace-base \
@opentelemetry/sdk-trace-node
AWS Lambda 包装器代码
此文件包含了所有的 OpenTelemetry 逻辑,用于启用跟踪。将以下代码保存为 lambda-wrapper.js
。
/* lambda-wrapper.js */
const api = require('@opentelemetry/api');
const { BatchSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const {
OTLPTraceExporter,
} = require('@opentelemetry/exporter-trace-otlp-http');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
api.diag.setLogger(new api.DiagConsoleLogger(), api.DiagLogLevel.ALL);
const provider = new NodeTracerProvider();
const collectorOptions = {
url: '<后端地址>',
};
const spanProcessor = new BatchSpanProcessor(
new OTLPTraceExporter(collectorOptions),
);
provider.addSpanProcessor(spanProcessor);
provider.register();
registerInstrumentations({
instrumentations: [
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-aws-lambda': {
disableAwsContextPropagation: true,
},
}),
],
});
请将 <后端地址>
替换为您喜欢的后端的 URL,以便将所有跟踪导出到该后端。如果您还没有设置后端,请参考Jaeger或Zipkin。
请注意,将 disableAwsContextPropagation
设置为 true。原因是 Lambda 仪表化尝试默认使用 X-Ray 上下文头,除非为该函数启用了活动跟踪,否则将会生成非采样上下文,从而创建一个 NonRecordingSpan
。
有关详细信息,请参阅仪表化文档。
AWS Lambda 函数处理程序
现在您有了一个 Lambda 包装器,创建一个简单的处理程序,作为 Lambda 函数。将以下代码保存为 handler.js
。
/* handler.js */
'use strict';
const https = require('https');
function getRequest() {
const url = 'https://opentelemetry.io/';
return new Promise((resolve, reject) => {
const req = https.get(url, (res) => {
resolve(res.statusCode);
});
req.on('error', (err) => {
reject(new Error(err));
});
});
}
exports.handler = async (event) => {
try {
const result = await getRequest();
return {
statusCode: result,
};
} catch (error) {
return {
statusCode: 400,
body: error.message,
};
}
};
部署
有多种方式可以部署您的 Lambda 函数:
这里我们将使用 Serverless Framework,更多详情请参考在 Serverless Framework 指南中设置。
创建一个名为 serverless.yml
的文件:
service: lambda-otel-native
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs14.x
region: '<您的区域>'
environment:
NODE_OPTIONS: --require lambda-wrapper
functions:
lambda-otel-test:
handler: handler.hello
为了让 OpenTelemetry 正常工作,必须在任何其他文件之前包括 lambda-wrapper.js
:NODE_OPTIONS
设置确保了这一点。
注意,如果您不使用 Serverless Framework 部署 Lambda 函数,您必须使用 AWS 控制台 UI 手动添加此环境变量。
最后,运行以下命令将项目部署到 AWS:
serverless deploy
您现在可以使用 AWS 控制台 UI 调用新部署的 Lambda 函数。您应该期望看到与 Lambda 函数调用相关的跟踪。
访问后端
您现在应该能够在后端中查看 OpenTelemetry 从 Lambda 函数产生的跟踪!
GCP function
以下展示了如何使用 Google Cloud Platform(GCP)UI 仪表化通过 HTTP 触发的函数。
创建函数
登录 GCP,创建或选择一个应放置您的函数的项目。在侧边菜单中,转到“无服务器”并选择“云函数”。然后,单击“创建函数”,选择第二代作为环境,提供一个函数名并选择区域。
设置 otelwrapper 的环境变量
如果封闭,请打开“运行时、构建、连接和安全设置”菜单,向下滚动并添加环境变量 NODE_OPTIONS
,其值为以下内容:
--require ./otelwrapper.js
选择运行时
在下一个屏幕(“代码”)中,选择 Node.js 版本 16 作为运行时。
创建 OTel 包装器
创建一个名为 otelwrapper.js
的新文件,用于仪表化您的服务。请确保提供 SERVICE_NAME
并设置 <your backend address>
。
/* otelwrapper.js */
const { Resource } = require('@opentelemetry/resources');
const {
SemanticResourceAttributes,
} = require('@opentelemetry/semantic-conventions');
const api = require('@opentelemetry/api');
const { BatchSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const {
OTLPTraceExporter,
} = require('@opentelemetry/exporter-trace-otlp-http');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const providerConfig = {
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: '<您的函数名>',
}),
};
api.diag.setLogger(new api.DiagConsoleLogger(), api.DiagLogLevel.ALL);
const provider = new NodeTracerProvider(providerConfig);
const collectorOptions = {
url: '<您的后端地址>',
};
const spanProcessor = new BatchSpanProcessor(
new OTLPTraceExporter(collectorOptions),
);
provider.addSpanProcessor(spanProcessor);
provider.register();
registerInstrumentations({
instrumentations: [getNodeAutoInstrumentations()],
});
添加软件包依赖项
将以下内容添加到您的 package.json
:
{
"dependencies": {
"@google-cloud/functions-framework": "^3.0.0",
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/auto-instrumentations-node": "^0.35.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.34.0",
"@opentelemetry/instrumentation": "^0.34.0",
"@opentelemetry/sdk-node": "^0.34.0",
"@opentelemetry/sdk-trace-base": "^1.8.0",
"@opentelemetry/sdk-trace-node": "^1.8.0",
"@opentelemetry/resources": "^1.8.0",
"@opentelemetry/semantic-conventions": "^1.8.0"
}
}
添加 HTTP 调用到函数
以下代码对 OpenTelemetry 网站进行了调用,以演示出站调用。
/* index.js */
const functions = require('@google-cloud/functions-framework');
const https = require('https');
functions.http('helloHttp', (req, res) => {
let url = 'https://opentelemetry.io/';
https
.get(url, (response) => {
res.send(`Response ${response.body}!`);
})
.on('error', (e) => {
res.send(`Error ${e}!`);
});
});
后端
如果您在 GCP VM 上运行 OTel collector,则可能需要创建 VPC 访问连接器以能够发送跟踪。
部署
在 UI 中选择部署,等待部署准备就绪。
测试
您可以使用测试标签中的云 Shell 测试该函数。