本文介紹通過opentelemetry-js SDK將Node.js應用的Trace資料接入到Log Service的操作步驟。
前提條件
- 已建立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}
Log ServiceProject的接入地址,格式為${project}.${region-endpoint}:Port,其中:
${project}:Log ServiceProject名稱。
${region-endpoint}:Log ServiceProject所在地區的訪問網域名稱,支援公網和阿里雲內網(傳統網路、VPC)。更多資訊,請參見服務入口。
Port:網路連接埠,固定為10010。
test-project.cn-hangzhou.log.aliyuncs.com:10010
${project}
Log ServiceProject名稱。
test-project
${instance}
Trace服務執行個體ID。更多資訊,請參見建立Trace執行個體。
test-traces
${access-key-id}
阿里雲帳號AccessKey ID。
建議您使用只具備Log ServiceProject寫入許可權的RAM使用者的AccessKey(包括AccessKey ID和AccessKey Secret)。授予RAM使用者向指定Project寫入資料許可權的具體操作,請參見授權。如何擷取AccessKey的具體操作,請參見存取金鑰。
無
${access-key-secret}
阿里雲帳號AccessKey Secret。
建議您使用只具備Log ServiceProject寫入許可權的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資料並發送到Log Service。更多資訊,請參見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