本文介绍通过opentelemetry-js SDK将Node.js应用的Trace数据接入到日志服务的操作步骤。
前提条件
- 已创建Trace实例。更多信息,请参见创建Trace实例。
- 已安装Node.js v8.5.0及以上版本的开发环境。
(推荐)方案一:半自动接入
Node.js支持在http、https、grpc、express、mysql、mongodb、redis等框架中通过引入依赖包的方式自动上传Trace数据。详细的框架列表请参见opentelemetry-node-js-contrib。此处以express为例,介绍半自动接入方案。更多示例请参见examples。
- 安装依赖包。
npm install --save @opentelemetry/api npm install --save @opentelemetry/node npm install --save @opentelemetry/tracing npm install --save @opentelemetry/exporter-collector-grpc npm install --save @opentelemetry/instrumentation npm install --save @opentelemetry/instrumentation-express npm install --save @opentelemetry/instrumentation-http npm install --save @grpc/grpc-js npm install --save @opentelemetry/sdk-trace-node
- 初始化Tracer并启动express。
如下代码中的变量需根据实际情况替换。关于变量的详细说明,请参见变量说明。
const opentelemetry = require("@opentelemetry/api"); const { registerInstrumentations } = require("@opentelemetry/instrumentation"); const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node"); const { Resource } = require("@opentelemetry/resources"); const { SemanticResourceAttributes, } = require("@opentelemetry/semantic-conventions"); const { SimpleSpanProcessor, ConsoleSpanExporter, } = require("@opentelemetry/tracing"); const grpc = require("@grpc/grpc-js"); const { CollectorTraceExporter, } = require("@opentelemetry/exporter-collector-grpc"); const { ExpressInstrumentation, } = require("@opentelemetry/instrumentation-express"); const { HttpInstrumentation } = require("@opentelemetry/instrumentation-http"); var os = require("os"); var hostname = os.hostname(); const provider = new NodeTracerProvider({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: "${service}", [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: "${environment}", [SemanticResourceAttributes.SERVICE_VERSION]: "${version}", [SemanticResourceAttributes.SERVICE_NAMESPACE]: "${service.namespace}", [SemanticResourceAttributes.HOST_NAME]: hostname, }), }); provider.register(); registerInstrumentations({ instrumentations: [ new HttpInstrumentation(), new ExpressInstrumentation({ ignoreLayersType: [new RegExp("middleware.*")], }), ], tracerProvider: provider, }); var url = "${endpoint}"; var logStdout = false; if (url == "stdout") { logStdout = true; } var meta = new grpc.Metadata(); meta.add("x-sls-otel-project", "${project}"); meta.add("x-sls-otel-instance-id", "${instance}"); meta.add("x-sls-otel-ak-id", "${access-key-id}"); meta.add("x-sls-otel-ak-secret", "${access-key-secret}"); const collectorOptions = { url: url, credentials: grpc.credentials.createSsl(), metadata: meta, }; const exporter = new CollectorTraceExporter(collectorOptions); if (!logStdout) { provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); } else { var stdexporter = new ConsoleSpanExporter(); provider.addSpanProcessor(new SimpleSpanProcessor(stdexporter)); } provider.register(); var tracer = opentelemetry.trace.getTracer("${service}"); var express = require("express"); var app = express(); app.get("/hello", function (req, res, next) { res.send("success"); }); var server = app.listen(8079, function () { var port = server.address().port; console.log("App now running in %s mode on port %d", app.get("env"), port); });
表 1. 变量说明 变量 说明 示例 ${endpoint} 日志服务Project的接入地址,格式为${project}.${region-endpoint}:Port,其中: - ${project}:日志服务Project名称。
- ${region-endpoint}:日志服务Project所在地域的访问域名,支持公网和阿里云内网(经典网络、VPC)。更多信息,请参见服务入口。
- Port:网络端口,固定为10010。
test-project.cn-hangzhou.log.aliyuncs.com:10010 ${project} 日志服务Project名称。 test-project ${instance} Trace服务实例ID。更多信息,请参见创建Trace实例。 test-traces ${access-key-id} 阿里云账号AccessKey ID。 建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey(包括AccessKey ID和AccessKey Secret)。授予RAM用户向指定Project写入数据权限的具体操作,请参见授权。如何获取AccessKey的具体操作,请参见访问密钥。
无 ${access-key-secret} 阿里云账号AccessKey Secret。 建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey。
无 ${service} 服务名。根据您的实际场景取值。 payment ${version} 服务版本号。建议按照va.b.c格式定义。 v0.1.2 ${service.namespace} 服务归属的命名空间。 order ${environment} 服务部署环境。例如测试环境、预发环境、正式环境。 pre - 访问服务,触发Trace数据生成并发送。
127.0.0.1:8079/hello
方案二:手动构造Trace数据并发送
如果您使用的是自建框架或有其他需求,可以手动构造Trace数据并发送到日志服务。更多信息,请参见opentelemetry-js。
- 安装依赖包。
npm install --save @opentelemetry/api npm install --save @opentelemetry/node npm install --save @opentelemetry/tracing npm install --save @opentelemetry/exporter-collector-grpc
- 初始化Tracer并启动express。
如下代码中的变量需根据实际情况替换。更多信息,请参见变量说明。
const opentelemetry = require("@opentelemetry/api"); const { registerInstrumentations } = require("@opentelemetry/instrumentation"); const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node"); const { Resource } = require("@opentelemetry/resources"); const { SemanticResourceAttributes, } = require("@opentelemetry/semantic-conventions"); const { SimpleSpanProcessor, ConsoleSpanExporter, } = require("@opentelemetry/tracing"); const grpc = require("@grpc/grpc-js"); const { CollectorTraceExporter, } = require("@opentelemetry/exporter-collector-grpc"); const { ExpressInstrumentation, } = require("@opentelemetry/instrumentation-express"); const { HttpInstrumentation } = require("@opentelemetry/instrumentation-http"); var os = require("os"); var hostname = os.hostname(); const provider = new NodeTracerProvider({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: "${service}", [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: "${environment}", [SemanticResourceAttributes.SERVICE_VERSION]: "${version}", [SemanticResourceAttributes.SERVICE_NAMESPACE]: "${service.namespace}", [SemanticResourceAttributes.HOST_NAME]: hostname, }), }); provider.register(); registerInstrumentations({ instrumentations: [ new HttpInstrumentation(), new ExpressInstrumentation({ ignoreLayersType: [new RegExp("middleware.*")], }), ], tracerProvider: provider, }); var url = "${endpoint}"; var logStdout = false; if (url == "stdout") { logStdout = true; } var meta = new grpc.Metadata(); meta.add("x-sls-otel-project", "${project}"); meta.add("x-sls-otel-instance-id", "${instance}"); meta.add("x-sls-otel-ak-id", "${access-key-id}"); meta.add("x-sls-otel-ak-secret", "${access-key-secret}"); const collectorOptions = { url: url, credentials: grpc.credentials.createSsl(), metadata: meta, }; const exporter = new CollectorTraceExporter(collectorOptions); if (!logStdout) { provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); } else { var stdexporter = new ConsoleSpanExporter(); provider.addSpanProcessor(new SimpleSpanProcessor(stdexporter)); } provider.register(); var tracer = opentelemetry.trace.getTracer("${service}"); var express = require('express'); var app = express() app.get('/hello', function (req, res, next) { const span = tracer.startSpan('hello'); span.setAttribute('name', 'toma'); span.setAttribute('age', '26'); span.addEvent('invoking doWork'); res.send("success"); span.end(); }); var server = app.listen(8079, function () { var port = server.address().port; console.log("App now running in %s mode on port %d", app.get("env"), port); });
- 访问服务,触发Trace数据生成并发送。
127.0.0.1:8079/hello