全部產品
Search
文件中心

Simple Log Service:通過OpenTelemetry接入Node.js Trace資料

更新時間:Jun 30, 2024

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

  1. 安裝依賴包。
    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
  2. 初始化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
  3. 訪問服務,觸發Trace資料產生並發送。
    127.0.0.1:8079/hello

方案二:手動構造Trace資料並發送

如果您使用的是自建架構或有其他需求,可以手動構造Trace資料並發送到Log Service。更多資訊,請參見opentelemetry-js

  1. 安裝依賴包。
    npm install --save @opentelemetry/api
    npm install --save @opentelemetry/node
    npm install --save @opentelemetry/tracing
    npm install --save @opentelemetry/exporter-collector-grpc
  2. 初始化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);
    });
  3. 訪問服務,觸發Trace資料產生並發送。
    127.0.0.1:8079/hello

後續步驟