无服务器计算

使用 OpenTelemetry JavaScript 对无服务器函数进行仪表化

本指南展示了如何使用 OpenTelemetry 仪表化库来跟踪无服务器函数。

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,以便将所有跟踪导出到该后端。如果您还没有设置后端,请参考JaegerZipkin

请注意,将 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.jsNODE_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 测试该函数。

最后修改 December 10, 2023: translate (a4350d6e)