OpenCensus を使用してカスタム指標を作成する

OpenCensus は無料のオープンソース プロジェクトで、そのライブラリによって次のことが可能になります。

  • 複数の言語にわたる指標データとトレースデータの、ベンダーに依存しないサポートを提供する。
  • エクスポータを使用して、収集したデータを Cloud Monitoring を含むさまざまなバックエンド アプリケーションにエクスポートする。

Cloud Monitoring は、カスタム指標の定義と収集をサポートする APIを提供しますが、これは低レベルの独自仕様の API です。OpenCensus は、言語コミュニティのスタイルに従う API を提供し、Monitoring API を通じて指標データを Cloud Monitoring に送信するエクスポータも用意しています。

OpenCensus は、アプリケーション トレースのための優れたサポートも備えています。一般的な概要については、OpenCensus のトレースをご覧ください。Cloud Trace では、トレース手段として OpenCensus を使用することをおすすめします。サービスから指標データとトレースデータの両方を収集するには、ライブラリの単一のディストリビューションを使用します。Cloud Trace で OpenCensus を使用する方法については、Trace 用のクライアント ライブラリをご覧ください。

始める前に

Cloud Monitoring を使用するには、課金を有効にした Cloud プロジェクトが必要です。 必要に応じて、次のことを行います。

  1. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  2. Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

  3. Monitoring API が有効であることを確認します。詳細については、Monitoring API の有効化をご覧ください。
  4. Google Cloud の外部で実行されているアプリケーションの場合、Cloud プロジェクトでアプリケーションを認証する必要があります。通常は、プロジェクト用のサービス アカウントを作成し、環境変数を構成することによって、認証を構成します。

    Amazon Elastic Compute Cloud(Amazon EC2)インスタンスで実行するアプリケーションの場合は、インスタンスの AWS コネクタ プロジェクトのサービス アカウントを作成します。

    サービス アカウントの作成については、認証の開始をご覧ください。

OpenCensus をインストールする

OpenCensus によって収集された指標を Google Cloud プロジェクトで使用するには、OpenCensus 指標ライブラリと Stackdriver エクスポータをアプリケーションで使用できるようにする必要があります。Stackdriver エクスポータは、OpenCensus が収集した指標を Google Cloud プロジェクトにエクスポートします。その後、Cloud Monitoring を使用して、これらの指標をグラフ化またはモニタリングできます。

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

requirements.txt ファイルは、python-docs-samples サンプル用の GitHub リポジトリにあります。

OpenCensus でカスタム指標を書き込む

指標のために OpenCensus を使用するようにコードを記述するには、以下の 3 つの手順を行います。

  1. OpenCensus 統計情報と OpenCensus Stackdriver エクスポータ パッケージをインポートします。
  2. Stackdriver エクスポータを初期化します。
  3. OpenCensus API を使用してコードを記述します。

次の例は、OpenCensus を使用して指標データを書き込む最小のプログラムです。このプログラムはレイテンシの測定値を繰り返し収集して、繰り返しを終了する際には、Cloud 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 = process.env.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.');
  globalStats.unregisterExporter(exporter);
}, 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))

    # Register exporter to the view manager.
    stats.stats.view_manager.register_exporter(exporter)

    # Record 100 fake latency values between 0 and 5 seconds.
    for num in range(100):
        ms = random() * 5 * 1000

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

        print("Fake latency recorded ({}: {})".format(num, ms))

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

if __name__ == '__main__':
    main()
この指標データを Cloud Monitoring にエクスポートすると、他のデータと同じ様に使用できます。

このプログラムは、task_latency_distribution と呼ばれる OpenCensus ビューを作成します。この文字列は、Cloud Monitoring にエクスポートされる際に指標の名前の一部になります。OpenCensus ビューが Cloud Monitoring の指標記述子としてどのように実現されるかは、指標記述子の取得をご覧ください。 ビュー名は、グラフ化する指標を選択するときに、検索文字列として使用できます。

サンプル プログラムを実行している場合は、Metrics Explorer を使用してデータを見ることができます。
  1. Google Cloud Console で、Monitoring の [Metrics Explorer] ページに移動します。
  2. Metrics Explorer に移動

  3. ツールバーで [エクスプローラ] タブを選択します。
  4. [CONFIGURATION] タブを選択します。
  5. [指標を選択] メニューを開き、フィルタバーに「OpenCensus/task_latency_distribution」と入力し、サブメニューを使用して特定のリソースタイプと指標を選択します。
    1. [アクティブなリソース] メニューで、モニタリング対象リソースを選択します。プログラムをローカル環境で実行する場合は、[グローバル] を選択します。
    2. [アクティブな指標カテゴリ] メニューで、[カスタム] を選択します。
    3. [アクティブな指標] メニューで、[タスクのレイテンシの分布] を選択します。
    4. [適用] をクリックします。
  6. 省略可: データの表示方法を構成するには、フィルタを追加し、[Group By]、[Aggregator]、グラフタイプの各メニューを使用します。このグラフでは、[折れ線グラフ] メニューを展開して [ヒートマップ グラフ] を選択します。 詳細については、Metrics Explorer 使用時の指標の選択をご覧ください。
  7. 省略可: グラフの設定を変更します。
    • 割り当てと、1 日に 1 つのサンプルを報告するその他の指標については、期間を 1 週間以上に設定し、プロットタイプを [積み上げ棒グラフ] に設定します。
    • 分布値の指標の場合、プロットタイプをヒートマップ グラフに設定します。

次のスクリーンショットでは、ローカル環境でプログラムを実行した後に収集された時系列を示します。

Cloud Monitoring の OpenCensus からの指標。

ヒートマップの各バーは、プログラムの 1 回の実行を表し、各バーの色付きのコンポーネントは、レイテンシ分布のバケットを表します。

Cloud Monitoring で OpenCensus 指標を読み取る

OpenCensus によって書き込まれた指標などのカスタム指標は、組み込み指標のように使用します。これらの指標は、グラフ化、アラートの設定、読み取りが可能です。

このセクションでは、API Explorer を使用して指標データを読み取る方法について説明します。Cloud Monitoring API またはクライアント ライブラリを使用して指標データを読み取る方法については、次のドキュメントをご覧ください。

  • 指標の閲覧では、カスタム指標と組み込み指標を一覧表示して調べる方法が説明されています。
  • 指標の読み取りでは、Monitoring API を使用してカスタム指標や組み込み指標から時系列データを取得する方法が説明されています。

たとえば、前のセクションに示されているスクリーンショットは Metrics Explorer のものです。グラフツールを使用する場合は、OpenCensus ビューの名前を使用して指標のリストをフィルタリングすることをおすすめします。詳細については、Metrics Explorer 使用時の指標の選択をご覧ください。

指標記述子を取得する

Monitoring API を直接使用して指標データを取得するには、OpenCensus 指標がエクスポートされた Cloud Monitoring の名前を確認する必要があります。名前を取得するには、エクスポータが作成する指標記述子を取得し、type フィールドを確認します。指標記述子の詳細については、MetricDescriptor をご覧ください。

エクスポートされた指標用に作成された指標記述子を表示するには、次のようにします。

  1. metricDescriptors.list リファレンス ページに移動します。
  2. リファレンス ページの [この API を試す] ウィジェットで、次のフィールドに値を入力します。

    1. name フィールドに、プロジェクトの名前を入力します。名前の構造は「projects/PROJECT_ID」の形式です。 このドキュメントでは、ID が a-gcp-project のプロジェクトを使用します。

    2. filter フィールドにフィルタを入力します。プロジェクトには多くの指標記述子があります。フィルタリングにより、関心のない記述子を削除できます。

      たとえば、OpenCensus ビューの名前は指標名の一部になるため、次のようなフィルタを追加できます。

      metric.type=has_substring("task_latency_distribution")

      キー metric.type は、時系列に埋め込まれるタイプのフィールドです。詳しくは、TimeSeries をご覧ください。

    3. [実行] をクリックします。

返された指標記述子を以下に示します。

    {
      "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"
        }
      ]
    }

指標記述子の中の次の行に、Cloud Monitoring の指標タイプの名前が表示されます。

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

これで、指標タイプに関連付けられたデータを手動で取得するために必要な情報が得られました。指標のグラフを作成するとき、type フィールドの値も Google Cloud Console に表示されます。

指標データを取得する

指標タイプから時系列データを手動で取得するには、次のようにします。

  1. timeSeries.list リファレンス ページに移動します。
  2. リファレンス ページの [この API を試す] ウィジェットで、次のフィールドに値を入力します。

    1. name フィールドに、プロジェクトの名前を入力します。名前の構造は「projects/PROJECT_ID」の形式です。
    2. filter フィールドに次の値を入力します。

      metric.type="custom.googleapis.com/opencensus/task_latency_distribution"

    3. interval.startTime フィールドと interval.endTime フィールドの値を入力します。これらの値はタイムスタンプとして入力する必要があります(例: 2018-10-11T15:48:38-04:00)。startTime 値が 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 インスタンス上で実行するプログラムから取得されたものです。他のモニタリング対象リソースの使用方法については、エクスポータ用のモニタリング対象リソースの設定をご覧ください。
  • 指標の種類と値のタイプの説明。
  • 要求された時間間隔内に収集された実際のデータポイント。

Monitoring による OpenCensus 指標の表現

カスタム指標用に Cloud Monitoring API を直接使用することがサポートされています。この使用方法については、API を使用してカスタム指標を作成するをご覧ください。実際に、Cloud Monitoring 用の OpenCensus エクスポータでは、この API が使用されています。 このセクションでは、OpenCensus によって書き込まれた指標を、Cloud Monitoring で表示する方法について説明します。

OpenCensus API で使用される構造は、Cloud Monitoring で使用される構造とは異なり、用語の使用法も一部異なります。Cloud Monitoring で言う「指標」は、OpenCensus では「stats(統計)」と呼ばれることがあります。たとえば、指標データを Cloud Monitoring に送信する OpenCensus のコンポーネントは、「Stackdridiver 用の Stats Exporter」と呼ばれます。

指標の OpenCensus モデルの概要については、OpenCensus の指標をご覧ください。

OpenCensus 統計情報と Cloud Monitoring 指標のデータモデルは、1 対 1 のマッピングにまとめきれません。コンセプトの多くはそれぞれで同じですが、それらを直接置き換えることができないためです。

  • 通常、OpenCensus のビューは Monitoring API の MetricDescriptor に似ています。ビューは、個々の測定値を収集して集計する方法を記述するものです。 タグは、記録されたすべての測定値に含まれます。

  • OpenCensus のタグは Key-Value ペアです。OpenCensus タグは、通常、Monitoring API の LabelDescriptor に対応します。タグを使用すると、指標のフィルタやグループ化に使用できるコンテキスト情報を取得できます。

  • OpenCensus の測定は、記録される指標データを記述します。OpenCensus の集計は、集計用のデータに適用される機能です。これらの機能は、エクスポート時に Cloud Monitoring 指標記述子で報告される MetricKindValueType、および単位を決定するために使用されます。

  • OpenCensus の測定値は、収集されたデータポイントです。測定値はビューに集約される必要があります。そうでない場合、個々の測定値は削除されます。OpenCensus の測定値は、Monitoring API における Point のようなものです。ビューで測定値が集計されると、その集計データは、Monitoring API の TimeSeries に似たビューデータとして格納されます。

次のステップ