全部產品
Search
文件中心

Managed Service for OpenTelemetry:通過OpenTelemetry上報Node.js應用資料

更新時間:Aug 08, 2024

通過OpenTelemetry為應用埋點並上報鏈路資料至Managed Service for OpenTelemetry後,Managed Service for OpenTelemetry即可開始監控應用,您可以查看應用拓撲、調用鏈路、異常事務、慢事務和SQL分析等一系列監控資料。本文介紹如何使用OpenTelemetry對Node.js Express應用進行自動或手動埋點並上報資料。

前提條件

重要

Node.js版本需要14及以上,其他版本請使用Jaeger接入。Jaeger接入操作,請參見通過Jaeger上報Node.js應用資料

擷取存取點資訊

新版控制台

  1. 登入可觀測鏈路 OpenTelemetry 版控制台,在左側導覽列單擊接入中心

  2. 開源架構地區單擊OpenTelemetry卡片。

  3. 在彈出的OpenTelemetry面板中選擇資料需要上報的地區。

    說明

    初次接入的地區將會自動進行資源初始化。

  4. 選擇串連方式上報方式,然後複製存取點資訊。

    • 串連方式:若您的服務部署在阿里雲上,且所屬地區與選擇的接入地區一致,推薦使用阿里雲內網方式,否則選擇公網方式。

    • 上報方式:根據用戶端支援的協議類型選擇HTTP或gRPC協議上報資料。

    image.png

舊版控制台

  1. 登入可觀測鏈路 OpenTelemetry 版控制台

  2. 在左側導覽列單擊叢集配置,然後在右側頁面單擊存取點資訊頁簽。

  3. 在頁面頂部選擇需要接入的地區,然後在叢集資訊地區開啟顯示Token開關。

  4. 用戶端採集工具地區單擊OpenTelemetry

    相關資訊列中,擷取存取點資訊。ot舊版中.jpg

    說明

    如果應用部署於阿里雲生產環境,則選擇阿里雲VPC網路存取點,否則選擇公網存取點。

背景資訊

OpenTelemetry提供了若干自動埋點外掛程式,支援為常見架構自動建立Span,支援的架構列表如下,完整資訊請參見OpenTelemetry官方文檔

展開查看支援的Node.js架構

樣本Demo

範例程式碼倉庫地址:opentelemetry-nodejs-demo

方法一:自動埋點(推薦)

  1. 下載運行專案所需的依賴。

    cd auto-instrumentation
    
    npm init -y
    npm install express
    npm install axios
  2. 下載OpenTelemetry自動埋點所需的依賴。

    npm install --save @opentelemetry/api
    npm install --save @opentelemetry/auto-instrumentations-node
  3. 編寫應用代碼。

    以下代碼是通過Express實現的簡單應用樣本:

    "use strict";
    
    const axios = require("axios").default;
    const express = require("express");
    const app = express();
    
    app.get("/", async (req, res) => {
      const result = await axios.get("http://localhost:7001/hello");
      return res.status(201).send(result.data);
    });
    
    app.get("/hello", async (req, res) => {
      console.log("hello world!")
      res.json({ code: 200, msg: "success" });
    });
    
    app.use(express.json());
    
    app.listen(7001, () => {
      console.log("Listening on http://localhost:7001");
    });
  4. 通過環境變數設定OpenTelemetry參數並運行應用。

    請將${httpEndpoint}替換為前提條件中擷取的HTTP存取點,請將${serviceName}替換為您的應用程式名稱。

    export OTEL_TRACES_EXPORTER="otlp"
    export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="${httpEndpoint}"
    export OTEL_NODE_RESOURCE_DETECTORS="env,host,os"
    export OTEL_SERVICE_NAME="${serviceName}"
    export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
    node main.js
    說明

    有關OpenTelemetry環境變數的說明,請參見OpenTelemetry Node.js自動埋點配置

  5. 訪問應用。

    通過以下命令訪問應用,或者直接在瀏覽器中訪問該地址,即可產生調用鏈並上報至Managed Service for OpenTelemetry

    curl localhost:7001/hello

方法二:手動埋點

  1. package.json中配置對OpenTelemetry的依賴。

     "dependencies": {
        "@opentelemetry/api": "^1.0.4",
        "@opentelemetry/exporter-trace-otlp-grpc": "^0.27.0",
        "@opentelemetry/instrumentation": "^0.27.0",
        "@opentelemetry/instrumentation-express": "^0.27.0",
        "@opentelemetry/instrumentation-http": "^0.27.0",
        "@opentelemetry/resources": "^1.0.1",
        "@opentelemetry/sdk-trace-base": "^1.0.1",
        "@opentelemetry/sdk-trace-node": "^1.0.1"
      }
  2. 建立Provider。

    const { Resource } = require("@opentelemetry/resources");
    const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
    const {
      SemanticResourceAttributes,
    } = require("@opentelemetry/semantic-conventions");
    
    const provider = new NodeTracerProvider({
      resource: new Resource({
        [SemanticResourceAttributes.HOST_NAME]: require("os").hostname(),
        [SemanticResourceAttributes.SERVICE_NAME]: "opentelemetry-express",    //opentelemetry-express可替換為任意名稱。
      }),
    });
  3. 通過Provider註冊HTTP和Express架構,自動監測並攔截HTTP和Express。

    說明

    如需監測其他架構下的Node.js應用,請參見OpenTelemetry官方文檔

    const { registerInstrumentations } = require("@opentelemetry/instrumentation");
    const { HttpInstrumentation } = require("@opentelemetry/instrumentation-http");
    const {
      ExpressInstrumentation,
    } = require("@opentelemetry/instrumentation-express");
    
    registerInstrumentations({
      tracerProvider: provider,
      instrumentations: [new HttpInstrumentation(), ExpressInstrumentation],
    });
  4. 配置Exporter,匯出資料到Managed Service for OpenTelemetry

    請將下面代碼中的<ENDPOINT><AUTHENTICATION>替換成前提條件中擷取的Endpoint和Authentication。

    const metadata = new grpc.Metadata();
    metadata.set("Authentication", "<AUTHENTICATION>");
    
    const exporter = new OTLPTraceExporter({ url: "<ENDPOINT>", metadata });
    provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
    provider.register();
  5. 可選:添加自訂事件和屬性。

    說明

    OpenTelemetry API的使用方法,請參見OpenTelemetry官方文檔

    const api = require("@opentelemetry/api");
    const currentSpan = api.trace.getSpan(api.context.active());
    currentSpan.addEvent("timestamp", { value: Date.now() });
    currentSpan.setAttribute("tagKey-01", "tagValue-01");

在控制台查看Trace

可觀測鏈路 OpenTelemetry 版控制台應用列表頁面選擇目標應用,查看鏈路資料。

基於Express架構的Node.js應用完整樣本

"use strict";

const { Resource } = require("@opentelemetry/resources");
const {
  OTLPTraceExporter,
} = require("@opentelemetry/exporter-trace-otlp-grpc");
const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
const { SimpleSpanProcessor } = require("@opentelemetry/sdk-trace-base");
const {
  ExpressInstrumentation,
} = require("@opentelemetry/instrumentation-express");
const { registerInstrumentations } = require("@opentelemetry/instrumentation");
const { HttpInstrumentation } = require("@opentelemetry/instrumentation-http");
const {
  SemanticResourceAttributes,
} = require("@opentelemetry/semantic-conventions");
const grpc = require("@grpc/grpc-js");

const provider = new NodeTracerProvider({
  resource: new Resource({
    [SemanticResourceAttributes.HOST_NAME]: require("os").hostname(),
    [SemanticResourceAttributes.SERVICE_NAME]: "opentelemetry-express",
  }),
});

registerInstrumentations({
  tracerProvider: provider,
  instrumentations: [new HttpInstrumentation(), ExpressInstrumentation],
});

const metadata = new grpc.Metadata();
metadata.set("Authentication", "<AUTHENTICATION>");

const exporter = new OTLPTraceExporter({ url: "<ENDPOINT>", metadata });
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();

// 應用代碼
const api = require("@opentelemetry/api");
const axios = require("axios").default;
const express = require("express");
const app = express();

app.get("/", async (req, res) => {
  const result = await axios.get("http://localhost:7001/api");
  return res.status(201).send(result.data);
});

app.get("/api", async (req, res) => {
  const currentSpan = api.trace.getSpan(api.context.active());
  currentSpan.addEvent("timestamp", { value: Date.now() });
  currentSpan.setAttribute("tagKey-01", "tagValue-01");
  res.json({ code: 200, msg: "success" });
});

app.use(express.json());

app.listen(7001, () => {
  console.log("Listening on http://localhost:7001");
});