使用 OpenCensus 的自訂指標

Stackdriver Monitoring 會從一長串的受控資源清單中自動收集上千個內建指標的相關資訊。但這些指標無法擷取特定應用程式資料或用戶端系統資料。這些指標可為您提供後端延遲或磁碟使用情形等資訊,但無法告知您應用程式產生的背景常式數量。

特定應用程式指標是指您定義與收集的指標,用於擷取內建的 Stackdriver Monitoring 指標無法取得的資訊。您可以使用程式庫提供的 API 來擷取這類指標以便設定程式碼,接著將指標傳送到 Stackdriver Monitoring 等後端應用程式。

在 Stackdriver Monitoring 中,特定應用程式指標通常稱為「自訂指標」。這些指標詞彙可交互使用,也稱為「使用者定義指標」。

就 Stackdriver Monitoring 而言,自訂指標的使用方式如同內建指標:您可以為這些指標建立圖表、設定快訊或加以監控。兩者的差別在於「您」必須負責對自訂指標進行定義、資料寫入或刪除作業,但您無法對內建指標執行這些操作。

有許多方法可以擷取自訂指標,包括使用原生 Stackdriver Monitoring API。Stackdriver 建議您使用 OpenCensus 設定程式碼來收集自訂指標。

什麼是 OpenCensus?

OpenCensus 是免費的開放原始碼專案,其程式庫可執行下列工作:

  • 提供各廠商通用的指標與追蹤資料收集作業的各種程式語言支援。
  • 將收集的資料匯出至各種後端應用程式,包括 Stackdriver。

如需目前支援的程式語言清單,請參閱程式語言支援一表。 如需目前可使用匯出工具的後端應用程式清單,請參閱匯出工具一文。

為何要使用 OpenCensus?

雖然 Stackdriver Monitoring 提供的 API 可以讓使用者定義及收集各類自訂指標,是屬於低階語言、特殊規格的 API。OpenCensus 則提供更符合我們語言習慣的 API,並且隨附匯出工具,可透過 Monitoring API 將指標資料傳送到 Stackdriver Monitoring。

此外,OpenCensus 是開放原始碼專案。您在匯出先前收集的資料時,可以使用各家廠商通用的程式庫取代專用程式庫。

OpenCensus 另外也針對應用程式追蹤提供完善的支援;如需一般總覽資訊,請參閱 OpenCensus Tracing。Stackdriver 建議使用 OpenCensus 做為追蹤工具。您可以使用相同的程式庫收集服務的指標資料與追蹤資料。如要瞭解如何將 OpenCensus 與 Stackdriver Trace 搭配使用,請參閱 Trace 的用戶端程式庫

事前準備

如要使用 Stackdriver Monitoring,您必須具有啟用計費功能的 GCP 專案,且該專案也須與 Stackdriver Workspace 建立關聯。Stackdriver Monitoring 使用 Workspaces 來組織管理受監控的 GCP 專案。

如果您沒有 GCP 專案,請執行下列指令:

  1. 登入您的 Google 帳戶。

    如果您沒有帳戶,請申請新帳戶

  2. 選取或建立 Google Cloud Platform 專案。

    前往「Manage resources」(管理資源) 頁面

  3. 請確認您已啟用 Google Cloud Platform 專案的計費功能。

    瞭解如何啟用計費功能

如要建立專案與 Workspace 的關聯,請參閱 Workspaces一文。

自訂指標是 Stackdriver Monitoring 的一項計費功能,因此可能產生與擷取指標相關聯的費用。如要進一步瞭解定價資訊,請參閱 Stackdriver 計價方式

安裝 OpenCensus

如要使用 OpenCensus,您必須將指標程式庫與 Stackdriver 匯出工具設為可供使用。

Go

使用 OpenCensus 需要 Go 版本 1.11 以上版本。系統將自動為您處理依附元件。

Java

若為 Maven 專案,請將下列內容新增到 pom.xml 檔案的 dependencies 元素:
<dependency>
  <groupId>io.opencensus</groupId>
  <artifactId>opencensus-api</artifactId>
  <version>${opencensus.version}</version>
</dependency>
<dependency>
  <groupId>io.opencensus</groupId>
  <artifactId>opencensus-impl</artifactId>
  <version>${opencensus.version}</version>
</dependency>
<dependency>
  <groupId>io.opencensus</groupId>
  <artifactId>opencensus-exporter-stats-stackdriver</artifactId>
  <version>${opencensus.version}</version>
</dependency>

Node.js

  1. 安裝 OpenCensus 核心與匯出工具程式庫前,請確認您已設定適當的 Node.js 開發環境
  2. 安裝 OpenCensus 最簡單的方法就是使用 npm
    npm install @opencensus/core
    npm install @opencensus/exporter-stackdriver
  3. require 陳述式 (如下所示) 置於應用程式主要指令碼或進入點的最上方,在其他程式碼之前
const {globalStats, MeasureUnit, AggregationType} = require('@opencensus/core');
const {StackdriverStatsExporter} = require('@opencensus/exporter-stackdriver');

Python

使用下列指令安裝 OpenCensus 核心與 Stackdriver 匯出工具程式庫:

pip install -r opencensus/requirements.txt

使用 OpenCensus 取得指標資料

設定程式碼使用 OpenCensus 取得指標資料通常包含三個步驟:

  1. 匯入 OpenCensus 統計資料與 OpenCensus Stackdriver 匯出工具套件。
  2. 初始化 Stackdriver 匯出工具。
  3. 使用 OpenCensus API 設定程式碼。

基本示例

以下是用於說明這些步驟的極簡版程式。這個程式會執行單次循環並收集延遲測量資料,然後在循環結束時,將統計資料匯出到 Stackdriver Monitoring 後結束程式:

Go

// metrics_quickstart is an example of exporting a custom metric from
// OpenCensus to Stackdriver.
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"contrib.go.opencensus.io/exporter/stackdriver"
	"go.opencensus.io/stats"
	"go.opencensus.io/stats/view"
	"golang.org/x/exp/rand"
)

var (
	// The task latency in milliseconds.
	latencyMs = stats.Float64("task_latency", "The task latency in milliseconds", "ms")
)

func main() {
	ctx := context.Background()

	// Register the view. It is imperative that this step exists,
	// otherwise recorded metrics will be dropped and never exported.
	v := &view.View{
		Name:        "task_latency_distribution",
		Measure:     latencyMs,
		Description: "The distribution of the task latencies",

		// Latency in buckets:
		// [>=0ms, >=100ms, >=200ms, >=400ms, >=1s, >=2s, >=4s]
		Aggregation: view.Distribution(0, 100, 200, 400, 1000, 2000, 4000),
	}
	if err := view.Register(v); err != nil {
		log.Fatalf("Failed to register the view: %v", err)
	}

	// Enable OpenCensus exporters to export metrics
	// to Stackdriver Monitoring.
	// Exporters use Application Default Credentials to authenticate.
	// See https://developers.google.com/identity/protocols/application-default-credentials
	// for more details.
	exporter, err := stackdriver.NewExporter(stackdriver.Options{})
	if err != nil {
		log.Fatal(err)
	}
	// Flush must be called before main() exits to ensure metrics are recorded.
	defer exporter.Flush()

	if err := exporter.StartMetricsExporter(); err != nil {
		log.Fatalf("Error starting metric exporter: %v", err)
	}
	defer exporter.StopMetricsExporter()

	// Record 100 fake latency values between 0 and 5 seconds.
	for i := 0; i < 100; i++ {
		ms := float64(5*time.Second/time.Millisecond) * rand.Float64()
		fmt.Printf("Latency %d: %f\n", i, ms)
		stats.Record(ctx, latencyMs.M(ms))
		time.Sleep(1 * time.Second)
	}

	fmt.Println("Done recording metrics")
}

Java

import com.google.common.collect.Lists;

import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter;
import io.opencensus.stats.Aggregation;
import io.opencensus.stats.BucketBoundaries;
import io.opencensus.stats.Measure.MeasureLong;
import io.opencensus.stats.Stats;
import io.opencensus.stats.StatsRecorder;
import io.opencensus.stats.View;
import io.opencensus.stats.View.Name;
import io.opencensus.stats.ViewManager;

import java.io.IOException;
import java.util.Collections;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class Quickstart {
  private static final int EXPORT_INTERVAL = 70;
  private static final MeasureLong LATENCY_MS = MeasureLong.create(
      "task_latency",
      "The task latency in milliseconds",
      "ms");
  // Latency in buckets:
  // [>=0ms, >=100ms, >=200ms, >=400ms, >=1s, >=2s, >=4s]
  private static final BucketBoundaries LATENCY_BOUNDARIES = BucketBoundaries.create(
      Lists.newArrayList(0d, 100d, 200d, 400d, 1000d, 2000d, 4000d));
  private static final StatsRecorder STATS_RECORDER = Stats.getStatsRecorder();

  public static void main(String[] args) throws IOException, InterruptedException {
    // Register the view. It is imperative that this step exists,
    // otherwise recorded metrics will be dropped and never exported.
    View view = View.create(
        Name.create("task_latency_distribution"),
        "The distribution of the task latencies.",
        LATENCY_MS,
        Aggregation.Distribution.create(LATENCY_BOUNDARIES),
        Collections.emptyList());

    ViewManager viewManager = Stats.getViewManager();
    viewManager.registerView(view);

    // Enable OpenCensus exporters to export metrics to Stackdriver Monitoring.
    // Exporters use Application Default Credentials to authenticate.
    // See https://developers.google.com/identity/protocols/application-default-credentials
    // for more details.
    StackdriverStatsExporter.createAndRegister();

    // Record 100 fake latency values between 0 and 5 seconds.
    Random rand = new Random();
    for (int i = 0; i < 100; i++) {
      long ms = (long) (TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS) * rand.nextDouble());
      System.out.println(String.format("Latency %d: %d", i, ms));
      STATS_RECORDER.newMeasureMap().put(LATENCY_MS, ms).record();
    }

    // The default export interval is 60 seconds. The thread with the StackdriverStatsExporter must
    // live for at least the interval past any metrics that must be collected, or some risk being
    // lost if they are recorded after the last export.

    System.out.println(String.format(
        "Sleeping %d seconds before shutdown to ensure all records are flushed.", EXPORT_INTERVAL));
    Thread.sleep(TimeUnit.MILLISECONDS.convert(EXPORT_INTERVAL, TimeUnit.SECONDS));
  }
}

Node.js

'use strict';

const {globalStats, MeasureUnit, AggregationType} = require('@opencensus/core');
const {StackdriverStatsExporter} = require('@opencensus/exporter-stackdriver');

const EXPORT_INTERVAL = 60;
const LATENCY_MS = globalStats.createMeasureInt64(
  'task_latency',
  MeasureUnit.MS,
  'The task latency in milliseconds'
);

// Register the view. It is imperative that this step exists,
// otherwise recorded metrics will be dropped and never exported.
const view = globalStats.createView(
  'task_latency_distribution',
  LATENCY_MS,
  AggregationType.DISTRIBUTION,
  [],
  'The distribution of the task latencies.',
  // Latency in buckets:
  // [>=0ms, >=100ms, >=200ms, >=400ms, >=1s, >=2s, >=4s]
  [0, 100, 200, 400, 1000, 2000, 4000]
);

// Then finally register the views
globalStats.registerView(view);

// Enable OpenCensus exporters to export metrics to Stackdriver Monitoring.
// Exporters use Application Default Credentials (ADCs) to authenticate.
// See https://developers.google.com/identity/protocols/application-default-credentials
// for more details.
// Expects ADCs to be provided through the environment as ${GOOGLE_APPLICATION_CREDENTIALS}
// A Stackdriver workspace is required and provided through the environment as ${GOOGLE_PROJECT_ID}
const projectId = process.env.GOOGLE_PROJECT_ID;

// GOOGLE_APPLICATION_CREDENTIALS are expected by a dependency of this code
// Not this code itself. Checking for existence here but not retaining (as not needed)
if (!projectId || !process.env.GOOGLE_APPLICATION_CREDENTIALS) {
  throw Error('Unable to proceed without a Project ID');
}

// The minimum reporting period for Stackdriver is 1 minute.
const exporter = new StackdriverStatsExporter({
  projectId: projectId,
  period: EXPORT_INTERVAL * 1000,
});

// Pass the created exporter to Stats
globalStats.registerExporter(exporter);

// Record 100 fake latency values between 0 and 5 seconds.
for (let i = 0; i < 100; i++) {
  const ms = Math.floor(Math.random() * 5);
  console.log(`Latency ${i}: ${ms}`);
  globalStats.record([
    {
      measure: LATENCY_MS,
      value: ms,
    },
  ]);
}

/**
 * The default export interval is 60 seconds. The thread with the
 * StackdriverStatsExporter must live for at least the interval past any
 * metrics that must be collected, or some risk being lost if they are recorded
 * after the last export.
 */
setTimeout(() => {
  console.log('Done recording metrics.');
}, EXPORT_INTERVAL * 1000);

Python

from random import random
import time

from opencensus.ext.stackdriver import stats_exporter
from opencensus.stats import aggregation
from opencensus.stats import measure
from opencensus.stats import stats
from opencensus.stats import view

# A measure that represents task latency in ms.
LATENCY_MS = measure.MeasureFloat(
    "task_latency",
    "The task latency in milliseconds",
    "ms")

# A view of the task latency measure that aggregates measurements according to
# a histogram with predefined bucket boundaries. This aggregate is periodically
# exported to Stackdriver Monitoring.
LATENCY_VIEW = view.View(
    "task_latency_distribution",
    "The distribution of the task latencies",
    [],
    LATENCY_MS,
    # Latency in buckets: [>=0ms, >=100ms, >=200ms, >=400ms, >=1s, >=2s, >=4s]
    aggregation.DistributionAggregation(
        [100.0, 200.0, 400.0, 1000.0, 2000.0, 4000.0]))

def main():
    # Register the view. Measurements are only aggregated and exported if
    # they're associated with a registered view.
    stats.stats.view_manager.register_view(LATENCY_VIEW)

    # Create the Stackdriver stats exporter and start exporting metrics in the
    # background, once every 60 seconds by default.
    exporter = stats_exporter.new_stats_exporter()
    print('Exporting stats to project "{}"'
          .format(exporter.options.project_id))

    # Record 100 fake latency values between 0 and 5 seconds.
    for num in range(100):
        ms = random() * 5 * 1000
        print("Latency {}: {}".format(num, ms))

        mmap = stats.stats.stats_recorder.new_measurement_map()
        mmap.measure_float_put(LATENCY_MS, ms)
        mmap.record()

    # Keep the thread alive long enough for the exporter to export at least
    # once.
    time.sleep(65)

if __name__ == '__main__':
    main()
您在將這類指標資料匯出到 Stackdriver 後,即可使用指標資料;這些指標資料的使用方式與其他資料相同。

這個程式會建立名為 task_latency_distribution 的 OpenCensus 資料檢視。在匯出到 Stackdriver Monitoring 後,這個字串會成為指標名稱的一部分。如要瞭解如何將 OpenCensus 資料檢視做為 Stackdriver Monitoring 指標描述元,請參閱擷取指標描述元一節。

因此,您可以在選擇要建立圖表的指標時,使用資料檢視名稱做為搜尋字串。舉例來說,您可以將其輸入到 Metrics Explorer 的「Find resource type and metric」(尋找資源類型與指標) 欄位中。下列螢幕擷取畫面顯示了結果:

Stackdriver Monitoring 中的 OpenCensus 指標

熱視圖中的每個長條都代表每次的程式執行作業,而每個長條的彩色部分則代表延遲分佈的集區。如要進一步瞭解圖表背後的資料細節,請參閱 Stackdriver 中的 OpenCensus 指標

OpenCensus 說明文件

OpenCensus 為其指標 API 與 Stackdriver 匯出工具提供授權參考說明文件。下表提供這些參考說明文件的連結:

語言 API 參考說明文件 匯出工具說明文件 快速入門
Go Go API 統計資料與追蹤匯出工具 指標
Java Java API 統計資料匯出工具 指標
NodeJS NodeJS API 統計資料匯出工具 指標
Python Python API 統計資料匯出工具 指標

模型對應

原生的 Stackdriver Monitoring API 支援自訂指標功能;使用說明請參閱使用自訂指標一文。事實上,Stackdriver 的 OpenCensus 匯出工具會使用這個 API。

雖然您不需要知道 Stackdriver Monitoring API 的具體用法,熟悉其建構元件與術語仍然有助於瞭解 Stackdriver Monitoring 的指標呈現方式。本節針對這方面提供了一些背景資訊。

指標資料擷取到 Stackdriver 後,就會儲存在 Stackdriver Monitoring 建構元件中。舉例來說,您可以擷取自訂指標的指標描述元;這類描述元為 Monitoring API 的其中一種類型,詳情請參閱 MetricDescriptor。您會在某些情況下看到這些指標描述元,例如,為資料建立圖表時。

術語與概念

OpenCensus API 與 Stackdriver Monitoring 兩者所採用的建構元件有所不同,因此對於部分術語的使用方式也互有差異。Stackdriver Monitoring 所指的「指標」,在 OpenCensus 有時稱為「統計資料」。舉例來說,在 Stackdriver 中傳送指標資料的 OpenCensus 元件稱為「Stackdriver 統計資料匯出工具」。

如需 OpenCensus 模型的指標總覽,請參閱 OpenCensus 指標

OpenCensus 統計資料與 Stackdriver Monitoring 指標的資料模型並未完全對應。兩者有許多相同的概念,但無法直接通用。

  • OpenCensus 資料檢視大致類似於 Monitoring API 中的 MetricDescriptor。資料檢視說明如何收集與匯總個別測量點。所有記錄的測量點又可依照標記加以細分。

  • OpenCensus 標記為鍵/值組合,大致上可對應至 Monitoring API 中的 LabelDescriptor。您可以使用標記來擷取可用於指標篩選與分組的內容比對資訊。

  • OpenCensus 測量點是指要記錄的指標資料。OpenCensus 匯總則是套用到摘要資料的功能。這些項目會用於匯出作業,以判斷 MetricKindValueType 及 Stackdriver 指標描述元中的報告單位。

  • OpenCensus 測量點是指針對測量所收集的資料點。測量點必須匯總為資料檢視。如果未進行匯總,個別測量點就會遭到捨棄。這個建構元件類似於 Monitoring API 中的 Point。當測量點匯總於資料檢視時,匯總的資料會儲存為資料檢視的資料,類似於 Monitoring API 中的 TimeSeries

Stackdriver 中的 OpenCensus 指標

您可以在 Stackdriver Monitoring 中查看匯出的指標。基本示例中的螢幕擷取畫面是從 Metrics Explorer 擷取而來。如果您已執行範例程式,則可使用 Metrics Explorer 查看資料:

前往 Metrics Explorer 頁面

當您想要指定指標以限制搜尋範圍時,您可以提供 OpenCensus 資料檢視名稱。詳情請參閱選擇指標

擷取指標描述元

您可以直接使用 Monitoring API 擷取指標資料。如要擷取指標資料,您需要知道 OpenCensus 指標要匯出到哪個 Stackdriver 的名稱。

為取得這項資訊,其中一種方法是擷取匯出工具建立的指標描述元,然後找到「type」欄位值。這個值會整合從中進行匯出的 OpenCensus 資料檢視的名稱。如需指標描述元的詳細資訊,請參閱 MetricDescriptor

您可以透過 metricDescriptors.list 方法參考資料頁面上的 API Explorer (試用這個 API) 小工具,查看針對匯出指標建立的指標描述元。如要使用這個工具擷取 OpenCensus 指標的指標描述元:

  1. 在「name」(名稱) 欄位中輸入專案名稱:projects/[PROJECT_ID] 本文件使用的是 ID 為 a-gcp-project 的專案。

  2. 在「filter」(篩選條件) 欄位中輸入要使用的篩選條件。OpenCensus 資料檢視名稱會成為指標名稱的一部分,因此您可以使用該名稱做為篩選條件來限制清單範圍,其指令如下:

    metric.type=has_substring("task_latency_distribution")

    每個專案中都會有許多指標描述元。以 OpenCensus 資料檢視名稱做為篩選子字串,將可排除大部分的項目。

  3. 按一下 [Execute] (執行) 按鈕。

以下顯示傳回的指標描述元:

{
  "metricDescriptors": [
    {
      "name": "projects/a-gcp-project/metricDescriptors/custom.googleapis.com/opencensus/task_latency_distribution",
      "labels": [
        {
          "key": "opencensus_task",
          "description": "Opencensus task identifier"
        }
      ],
      "metricKind": "CUMULATIVE",
      "valueType": "DISTRIBUTION",
      "unit": "ms",
      "description": "The distribution of the task latencies",
      "displayName": "OpenCensus/task_latency_distribution",
      "type": "custom.googleapis.com/opencensus/task_latency_distribution"
    }
  ]
}

指標描述元中的這行文字可為您提供 Stackdriver Monitoring 的指標類型名稱:

"type": "custom.googleapis.com/opencensus/task_latency_distribution"

透過這類資訊,您可以手動擷取與這個指標類型相關聯的資料。這也是這個指標會在圖表上出現的資料。

擷取指標資料

如要手動擷取指定指標類型的時間序列資料,您可以使用 timeSeries.list 方法參考資料頁面上的「試用這個 API」工具:

  1. 在「name」(名稱) 欄位中輸入專案名稱:projects/[PROJECT_ID]
  2. 在「filter」(篩選條件) 欄位中輸入適用的篩選條件,以擷取所要的指標類型: metric.type="custom.googleapis.com/opencensus/task_latency_distribution"
    • metric.type 鍵是嵌入在時間序列中的某個類型中的欄位。詳情請參閱 TimeSeries
    • 這是在擷取指標描述元中,從指標描述元中擷取的 type 值。
  3. 指定下列欄位值,以設定擷取的時間範圍:
    • interval.endTime 為時間戳記,例如:2018-10-11T15:48:38-04:00
    • interval.startTime (必須早於 interval.endTime)
  4. 按一下 [Execute] (執行) 按鈕。

以下顯示這類擷取作業的結果:

{
  "timeSeries": [
    {
      "metric": {
        "labels": {
          "opencensus_task": "java-3424@docbuild"
        },
        "type": "custom.googleapis.com/opencensus/task_latency_distribution"
      },
      "resource": {
        "type": "gce_instance",
        "labels": {
          "instance_id": "2455918024984027105",
          "zone": "us-east1-b",
          "project_id": "a-gcp-project"
        }
      },
      "metricKind": "CUMULATIVE",
      "valueType": "DISTRIBUTION",
      "points": [
        {
          "interval": {
            "startTime": "2019-04-04T17:49:34.163Z",
            "endTime": "2019-04-04T17:50:42.917Z"
          },
          "value": {
            "distributionValue": {
              "count": "100",
              "mean": 2610.11,
              "sumOfSquaredDeviation": 206029821.78999996,
              "bucketOptions": {
                "explicitBuckets": {
                  "bounds": [
                    0,
                    100,
                    200,
                    400,
                    1000,
                    2000,
                    4000
                  ]
                }
              },
              "bucketCounts": [
                "0",
                "0",
                "1",
                "6",
                "13",
                "15",
                "44",
                "21"
              ]
            }
          }
        }
      ]
    },
    [ ... data from additional program runs deleted ...]
  ]
}

此處傳回的資料包括:

  • 要在其中收集資料的受監控資源的相關資訊。 OpenCensus 可以自動偵測 gce_instancek8s_containeraws_ec2_instance 受監控資源。此資料來自在 Compute Engine 執行個體上執行的程式。如要瞭解如何使用其他受監控資源,請參閱為匯出工具設定受監控資源一文。
  • 指標種類與值類型的說明。
  • 要求的時間間隔內收集的實際資料點。
本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Stackdriver Monitoring
需要協助嗎?請前往我們的支援網頁