Node.js 檢測範例

本文說明如何檢測 Node.js JavaScript 應用程式,使用 OpenTelemetry SDK 和 OpenTelemetry 收集器收集追蹤記錄和指標資料。同時也會說明如何將結構化 JSON 記錄寫入標準輸出內容。如要試用檢測功能,請下載並執行範例應用程式。這個應用程式使用 Fastify 網頁架構,並產生記錄、指標和追蹤資料。

使用 OpenTelemetry 收集器時,您會透過 SDK 和 SDK 的 OTLP 處理中匯出工具,檢測應用程式。這項儀器與供應商無關。您也會部署 OpenTelemetry 收集器,接收來自程序內匯出工具的遙測資料,然後將該遙測資料匯出至 Google Cloud 專案。如要進一步瞭解收集器,請參閱「Google 打造的 OpenTelemetry 收集器」。

如果您的環境支援使用收集器,建議您使用 OpenTelemetry 收集器匯出遙測資料。在某些環境中,您必須使用程序內匯出工具,直接將資料傳送至Google Cloud 專案。如要瞭解程序內檢測,請參閱「從 Trace 匯出器遷移至 OTLP 端點」。

如要進一步瞭解插樁,請參閱下列文件:

關於手動和零程式碼檢測

對於這個語言,OpenTelemetry 將零程式碼檢測定義為從程式庫和架構收集遙測資料的做法,無須變更程式碼。不過,您必須安裝模組並設定環境變數。

本文未說明零程式碼插碼。如要瞭解該主題,請參閱「JavaScript 零程式碼檢測」。

如需一般資訊,請參閱「OpenTelemetry Instrumentation for Node」。

事前準備

  1. 登入 Google Cloud 帳戶。如果您是 Google Cloud新手,歡迎 建立帳戶,親自評估產品在實際工作環境中的成效。新客戶還能獲得價值 $300 美元的免費抵免額,可用於執行、測試及部署工作負載。
  2. 安裝 Google Cloud CLI。

  3. 若您採用的是外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

  4. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  5. 建立或選取 Google Cloud 專案。

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
    • 建立專案:如要建立專案,您需要「專案建立者」角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色。
    • 建立 Google Cloud 專案:

      gcloud projects create PROJECT_ID

      將 PROJECT_ID 替換為要建立的專案名稱。 Google Cloud

    • 選取您建立的 Google Cloud 專案:

      gcloud config set project PROJECT_ID

      將 PROJECT_ID 替換為 Google Cloud 專案名稱。

  6. 確認專案已啟用計費功能 Google Cloud 。

  7. 如果尚未啟用,請啟用 Cloud Logging、Cloud Monitoring、Cloud Trace 和 Telemetry API:

    啟用 API 時所需的角色

    如要啟用 API,您必須具備 serviceusage.services.enable 權限。如果您建立了專案,可能已透過「擁有者」角色 (roles/owner) 取得這項權限。否則,您可以透過「服務使用情形管理員」角色 (roles/serviceusage.serviceUsageAdmin) 取得這項權限。瞭解如何授予角色。

    gcloud services enable logging.googleapis.com monitoring.googleapis.com cloudtrace.googleapis.com telemetry.googleapis.com
  8. 安裝 Google Cloud CLI。

  9. 若您採用的是外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

  10. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  11. 建立或選取 Google Cloud 專案。

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
    • 建立專案:如要建立專案,您需要「專案建立者」角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色。
    • 建立 Google Cloud 專案:

      gcloud projects create PROJECT_ID

      將 PROJECT_ID 替換為要建立的專案名稱。 Google Cloud

    • 選取您建立的 Google Cloud 專案:

      gcloud config set project PROJECT_ID

      將 PROJECT_ID 替換為 Google Cloud 專案名稱。

  12. 確認專案已啟用計費功能 Google Cloud 。

  13. 如果尚未啟用,請啟用 Cloud Logging、Cloud Monitoring、Cloud Trace 和 Telemetry API:

    啟用 API 時所需的角色

    如要啟用 API,您必須具備 serviceusage.services.enable 權限。如果您建立了專案,可能已透過「擁有者」角色 (roles/owner) 取得這項權限。否則,您可以透過「服務使用情形管理員」角色 (roles/serviceusage.serviceUsageAdmin) 取得這項權限。瞭解如何授予角色。

    gcloud services enable logging.googleapis.com monitoring.googleapis.com cloudtrace.googleapis.com telemetry.googleapis.com
  14. 如要取得讓範例應用程式寫入記錄、指標和追蹤資料所需的權限,請要求管理員授予您下列 IAM 角色:

    • 專案的「記錄檔寫入者」 (roles/logging.logWriter) 角色
    • 專案的「Monitoring Metric Writer」 (roles/monitoring.metricWriter)
    • 專案的「Cloud 遙測資料追蹤記錄寫入者」 (roles/telemetry.tracesWriter)
    • 配額專案的服務使用情形用戶 (roles/serviceusage.serviceUsageConsumer)

    如果您在 Cloud Shell、 Google Cloud 資源或本機開發環境中執行範例,這些權限就已足夠。如要瞭解如何設定配額專案,請參閱「設定配額專案」。

    <0x

    如要取得查看記錄、指標和追蹤資料所需的權限,請要求管理員在專案中授予您下列 IAM 角色:

    如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。

    您或許也能透過自訂角色或其他預先定義的角色,取得必要權限。

為應用程式加入檢測功能,收集追蹤記錄、指標和記錄

如要設定應用程式,收集追蹤記錄和指標資料,並將結構化 JSON 寫入標準輸出,請按照本文後續章節所述步驟操作:

  1. 設定 OpenTelemetry
  2. 設定應用程式,預先載入 OpenTelemetry 設定
  3. 設定結構化記錄
  4. 寫入結構化記錄檔

設定 OpenTelemetry

OpenTelemetry Node.js SDK 的預設設定會使用 OTLP 通訊協定匯出追蹤記錄。此外,這個程式碼也會設定 OpenTelemetry,使用 W3C 追蹤內容格式傳播追蹤內容。這項設定可確保追蹤記錄中的範圍具有正確的父項與子項關係。

以下程式碼範例說明如何設定 OpenTelemetry 的 JavaScript 模組。

如要查看完整範例,請在範例工具列中選取 GitHub 標誌。


diag.setLogger(
  new DiagConsoleLogger(),
  opentelemetry.core.diagLogLevelFromString(
    opentelemetry.core.getStringFromEnv('OTEL_LOG_LEVEL'),
  ),
);

const sdk = new opentelemetry.NodeSDK({
  instrumentations: getNodeAutoInstrumentations({
    // Disable noisy instrumentations
    '@opentelemetry/instrumentation-fs': {enabled: false},
  }),
  resourceDetectors: getResourceDetectorsFromEnv(),
  metricReader: getMetricReader(),
});

try {
  sdk.start();
  diag.info('OpenTelemetry automatic instrumentation started successfully');
} catch (error) {
  diag.error(
    'Error initializing OpenTelemetry SDK. Your application is not instrumented and will not produce telemetry',
    error,
  );
}

// Gracefully shut down the SDK to flush telemetry when the program exits
process.on('SIGTERM', () => {
  sdk
    .shutdown()
    .then(() => diag.debug('OpenTelemetry SDK terminated'))
    .catch(error => diag.error('Error terminating OpenTelemetry SDK', error));
});

先前的程式碼範例會設定 OpenTelemetry,使用 OTLP 通訊協定匯出指標,並使用 @opentelemetry/auto-instrumentations-node 套件設定所有可用的 Node.js 檢測。

為確保所有待處理的遙測資料都已排清,且連線在應用程式關閉前已正常關閉,SIGTERM 處理常式會呼叫 shutdown。

如要瞭解詳情和設定選項,請參閱「零程式碼插碼設定」。

設定應用程式,預先載入 OpenTelemetry 設定

如要設定應用程式,使用 OpenTelemetry 寫入結構化記錄,並收集指標和追蹤資料,請更新應用程式的叫用,使用 Node.js --require 旗標預先載入檢測模組。使用 --require 標記可確保 OpenTelemetry 在應用程式啟動前完成初始化。詳情請參閱「OpenTelemetry Node.js 入門」。

下列程式碼範例說明 Dockerfile 如何傳遞 --require 標記:

CMD node --require ./build/src/instrumentation.js build/src/index.js 2>&1 | tee /var/log/app.log

設定結構化記錄

如要將追蹤資訊納入以 JSON 格式寫入標準輸出的記錄中,請將應用程式設定為以 JSON 格式輸出結構化記錄。

以下程式碼範例說明 Pino LoggerOptions 物件,該物件會將應用程式設定為輸出 JSON 結構化記錄:


// Expected attributes that OpenTelemetry adds to correlate logs with spans
interface LogRecord {
  trace_id?: string;
  span_id?: string;
  trace_flags?: string;
  [key: string]: unknown;
}

// https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity
const PinoLevelToSeverityLookup: Record<string, string | undefined> = {
  trace: 'DEBUG',
  debug: 'DEBUG',
  info: 'INFO',
  warn: 'WARNING',
  error: 'ERROR',
  fatal: 'CRITICAL',
};

export const loggerConfig = {
  messageKey: 'message',
  // Same as pino.stdTimeFunctions.isoTime but uses "timestamp" key instead of "time"
  timestamp(): string {
    return `,"timestamp":"${new Date(Date.now()).toISOString()}"`;
  },
  formatters: {
    log(object: LogRecord): Record<string, unknown> {
      // Add trace context attributes following Cloud Logging structured log format described
      // in https://cloud.google.com/logging/docs/structured-logging#special-payload-fields
      const {trace_id, span_id, trace_flags, ...rest} = object;

      return {
        'logging.googleapis.com/trace': trace_id,
        'logging.googleapis.com/spanId': span_id,
        'logging.googleapis.com/trace_sampled': trace_flags
          ? trace_flags === '01'
          : undefined,
        ...rest,
      };
    },
    // See
    // https://getpino.io/#/docs/help?id=mapping-pino-log-levels-to-google-cloud-logging-stackdriver-severity-levels
    level(label: string) {
      return {
        severity:
          PinoLevelToSeverityLookup[label] ?? PinoLevelToSeverityLookup['info'],
      };
    },
  },
} satisfies LoggerOptions;

先前的設定會從記錄訊息中擷取有效跨度的相關資訊,然後將該資訊做為屬性新增至 JSON 結構化記錄。這些屬性可用於將記錄與追蹤記錄相互關聯:

  • logging.googleapis.com/trace:與記錄項目相關聯的追蹤記錄資源名稱。
  • logging.googleapis.com/spanId:與記錄項目相關聯的追蹤記錄中的時距 ID。
  • logging.googleapis.com/trace_sampled:這個欄位的值必須是 true 或 false。

如要進一步瞭解這些欄位,請參閱 LogEntry 結構。

如要在 Fastify 中使用 Pino 設定,請在建立 Fastify 應用程式時傳遞記錄器設定物件:

// Create the Fastify app providing the Pino logger config
const fastify = Fastify({
  logger: loggerConfig,
});

寫入結構化記錄檔

如要編寫連結至追蹤記錄的結構化記錄,請使用 Fastify 提供的 Pino 記錄器。舉例來說,下列陳述式說明如何呼叫 Logger.info() 方法:

request.log.info({subRequests}, 'handle /multi request');

OpenTelemetry 會自動在 Pino 記錄項目中填入 OpenTelemetry Context 中目前有效範圍的範圍內容。然後,系統會將這個時距內容納入 JSON 記錄中,如「設定結構化記錄」一文所述。

執行設定為收集遙測資料的範例應用程式

範例應用程式中的檢測功能使用與供應商無關的格式,例如記錄資料的 JSON,以及指標和追蹤資料的 OTLP。應用程式也會使用 和 Fastify 架構。OpenTelemetry Collector 會使用 Google 匯出工具,將記錄和指標資料傳送至專案。這項工具會使用 Telemetry API (採用 OTLP),將追蹤記錄資料傳送至專案。

這個應用程式有兩個端點:

  • /multi 端點是由 handleMulti 函式處理。應用程式中的負載產生器會向 /multi 端點發出要求。這個端點收到要求後,會向本機伺服器上的 /single 端點傳送三到七個要求。

    /**
     * handleMulti handles an http request by making 3-7 http requests to the /single endpoint.
     *
     * OpenTelemetry instrumentation requires no changes here. It will automatically generate a
     * span for the handler body.
     */
    fastify.get('/multi', async request => {
      const subRequests = randInt(3, 8);
      request.log.info({subRequests}, 'handle /multi request');
    
      for (let i = 0; i < subRequests; i++) {
        await axios.get(`http://localhost:${port}/single`);
      }
      return 'ok';
    });
  • /single 端點是由 handleSingle 函式處理。這個端點收到要求後,會短暫休眠,然後以字串回應。

    /**
     * handleSingle handles an http request by sleeping for 100-200 ms. It writes the number of
     * milliseconds slept as its response.
     */
    fastify.get('/single', async request => {
      // Sleep between 100-200 milliseconds
      const sleepMillis = randInt(100, 200);
      request.log.info({sleepMillis}, 'Going to sleep');
      await sleep(sleepMillis);
      return `slept ${sleepMillis}\n`;
    });

下載及部署應用程式

如要執行範例,請按照下列步驟操作:

  1. 在 Google Cloud 控制台中啟用 Cloud Shell。

    啟用 Cloud Shell

    控制台底部會開啟 Cloud Shell 工作階段,並顯示指令列提示。 Google Cloud Cloud Shell 是已安裝 Google Cloud CLI 的殼層環境,並已針對您目前的專案設定好相關值。工作階段可能要幾秒鐘的時間才能初始化。

  2. 複製存放區:

    git clone https://github.com/GoogleCloudPlatform/opentelemetry-samples
    
  3. 前往範例目錄:

    cd opentelemetry-samples/javascript/instrumentation-quickstart
    
  4. 建構並執行範例:

    docker compose up --abort-on-container-exit
    

    如果不是在 Cloud Shell 中執行,請執行應用程式,並讓 GOOGLE_APPLICATION_CREDENTIALS 環境變數指向憑證檔案。應用程式預設憑證會在 $HOME/.config/gcloud/application_default_credentials.json 提供憑證檔案。

    # Set environment variables
    export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
    export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json"
    export USERID="$(id -u)"
    
    # Run
    docker compose -f docker-compose.yaml -f docker-compose.creds.yaml up --abort-on-container-exit
    

查看指標

範例應用程式中的 OpenTelemetry 檢測會產生 Prometheus 指標,您可以使用 Metrics Explorer 查看這些指標:

  • Prometheus/http_server_duration_milliseconds/histogram 記錄伺服器要求的持續時間,並將結果儲存在直方圖中。

  • Prometheus/http_client_duration_milliseconds/histogram 記錄用戶端要求的持續時間,並將結果儲存在直方圖中。

如要查看範例應用程式產生的指標,請按照下列步驟操作:
  1. 前往 Google Cloud 控制台的 「指標探索器」頁面:

    前往 Metrics Explorer

    如果您是使用搜尋列尋找這個頁面,請選取子標題為「Monitoring」的結果。

  2. 在 Google Cloud 控制台的工具列中,選取 Google Cloud 專案。 如要進行 App Hub 設定,請選取 App Hub 主專案或已啟用應用程式的資料夾管理專案。
  3. 在「指標」元素中,展開「選取指標」選單, 在篩選列中輸入 http_server, 然後使用子選單選取特定資源類型和指標:
    1. 在「Active resources」(有效資源) 選單中,選取「Prometheus Target」(Prometheus 目標)。
    2. 在「使用中的指標類別」選單中,選取「Http」。
    3. 在「使用中的指標」選單中,選取指標。
    4. 按一下「套用」。
  4. 如要新增篩選器,從查詢結果中移除時間序列,請使用「Filter」元素。

  5. 設定資料的查看方式。

    如果指標的評估結果是累計值,Metrics Explorer 會自動以對齊期間將評估資料正規化,因此圖表會顯示比率。詳情請參閱「種類、型別和轉換」。

    測量整數或雙精度值時 (例如使用兩個 counter 指標),Metrics Explorer 會自動加總所有時間序列。如要查看 /multi 和 /single HTTP 路由的資料,請將「Aggregation」(彙整) 項目中的第一個選單設為「None」(無)。

    如要進一步瞭解如何設定圖表,請參閱「使用 Metrics Explorer 時選取指標」。

查看追蹤記錄

追蹤資料可能需要幾分鐘才會顯示。舉例來說,當專案收到追蹤記錄資料時,Google Cloud Observability 可能需要建立資料庫來儲存該資料。建立資料庫可能需要幾分鐘,這段期間無法查看任何追蹤資料。

如要查看追蹤記錄資料,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的 「Trace Explorer」頁面:

    前往「Trace explorer」(Trace 探索工具)

    您也可以透過搜尋列找到這個頁面。

  2. 在頁面的表格部分,選取含有範圍名稱 /multi 的資料列。
  3. 在「Trace details」(追蹤記錄詳細資料) 面板的甘特圖中,選取標示為 /multi 的時距。

    畫面上會開啟一個面板,顯示 HTTP 要求相關資訊。這些詳細資料包括方法、狀態碼、位元組數,以及呼叫者的使用者代理程式。

  4. 如要查看與這項追蹤記錄相關聯的記錄檔,請選取「記錄檔和事件」分頁標籤。

    這個分頁會顯示個別記錄。如要查看記錄項目的詳細資料,請展開記錄項目。您也可以按一下「查看記錄」,然後使用 Logs Explorer 查看記錄。

如要進一步瞭解如何使用 Cloud Trace 探索工具,請參閱「尋找及探索追蹤記錄」。

查看記錄檔

您可以在 Logs Explorer 中檢查記錄,也可以查看相關聯的追蹤記錄 (如有)。

  1. 前往 Google Cloud 控制台的 「Logs Explorer」頁面:

    前往「Logs Explorer」(記錄檔探索工具)

    如果您是使用搜尋列尋找這個頁面,請選取子標題為「Logging」的結果。

  2. 找出說明為 handle /multi request 的記錄。

    如要查看記錄詳細資料,請展開記錄項目。

  3. 在含有「handle /multi request」訊息的記錄項目中,按一下 Traces,然後選取 View trace details。

    系統會開啟「Trace details」面板,並顯示所選追蹤記錄。

    記錄資料可能比追蹤資料早幾分鐘提供。如果透過 ID 搜尋追蹤記錄或按照這項工作中的步驟查看追蹤記錄資料時發生錯誤,請稍候一兩分鐘,然後重試。

如要進一步瞭解如何使用 Logs Explorer,請參閱「使用 Logs Explorer 查看記錄檔」。

後續步驟