本文介紹通過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