使用 OpenCensus 创建用户定义的指标

OpenCensus 是一个免费的开源项目,该项目的库具有以下特点:

  • 可为收集多种语言的指标和跟踪记录数据提供不限定供应商的支持。
  • 可以使用导出器将收集的数据导出到各种后端应用,包括 Cloud Monitoring。

虽然 Cloud Monitoring 提供了一个支持定义和收集用户定义的指标的 API,但它属于低层级的专有 API。OpenCensus 提供了一个遵循语言社区风格的 API,以及一个导出器,该导出器可通过 Monitoring API 为您将指标数据发送到 Cloud Monitoring。

OpenCensus 还对应用跟踪提供了良好的支持。如需大致了解这项支持,请参阅 OpenCensus 跟踪。Cloud Trace 建议使用 OpenCensus 对跟踪记录进行插桩检测。如需从服务中收集指标和跟踪记录数据,您可以使用单一发行版的库。如需了解如何将 OpenCensus 与 Cloud Trace 配合使用,请参阅 Trace 的客户端库

准备工作

若要使用 Cloud Monitoring,您必须有启用了结算功能的 Google Cloud 项目。如有必要,请执行以下操作:

  1. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  2. 确保您的 Google Cloud 项目已启用结算功能

  3. 确保已启用 Monitoring API。如需了解详情,请参阅启用 Monitoring API
  4. 对于在 Google Cloud 外部运行的应用,您的 Google Cloud 项目必须对应用进行身份验证。通常,您可以通过为项目创建服务账号并配置环境变量来配置身份验证。

    对于在 Amazon Elastic Compute Cloud (Amazon EC2) 实例上运行的应用,请为该实例的 AWS 连接器项目创建服务帐号。

    如需了解如何创建服务账号,请参阅身份验证使用入门

安装 OpenCensus

要在 Google Cloud 项目中使用 OpenCensus 收集的指标,必须将 OpenCensus 指标库和 Stackdriver 导出器提供给您的应用。Stackdriver 导出器会将 OpenCensus 收集的指标导出到您的 Google Cloud 项目。然后,您可以使用 Cloud Monitoring 为这些指标绘制图表或监控这些指标。

Go

如需向 Monitoring 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

使用 OpenCensus 需要 Go 1.11 或更高版本。系统会自动为您处理依赖项。

Java

如需向 Monitoring 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

对于 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-exporter-stats-stackdriver</artifactId>
  <version>${opencensus.version}</version>
</dependency>

Node.js

如需向 Monitoring 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

  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

如需向 Monitoring 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

使用以下命令安装 OpenCensus 核心库和 Stackdriver 导出器库:

pip install -r opencensus/requirements.txt

requirements.txt 文件位于这些示例的 GitHub 代码库中,即 python-docs-samples

使用 OpenCensus 编写用户定义的指标

如需使用 OpenCensus 获取指标,您需要执行以下三个步骤来对代码进行插桩:

  1. 导入 OpenCensus 统计信息和 OpenCensus Stackdriver 导出器包。
  2. 初始化 Stackdriver 导出器。
  3. 使用 OpenCensus API 对代码进行插桩。

以下示例是一个使用 OpenCensus 写入指标数据的最精简程序。该程序运行一个循环并收集延迟时间指标;当循环结束时,它会将统计信息导出到 Cloud Monitoring 并退出运行:

Go

如需向 Monitoring 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


// 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

如需向 Monitoring 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


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

如需向 Monitoring 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

'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

如需向 Monitoring 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


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(f"Fake latency recorded ({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 时,该字符串会成为指标名称的一部分。如需了解如何以 Cloud Monitoring 指标描述符形式实现 OpenCensus 视图,请参阅检索指标描述符。 因此,在选择要绘制成图表的指标时,您可以使用视图名称作为搜索字符串。

如果您已运行示例程序,则可以使用 Metrics Explorer 查看您的数据:
  1. 在 Google Cloud 控制台的导航面板中,选择 Monitoring,然后选择  Metrics Explorer

    进入 Metrics Explorer

  2. 指标元素中,展开选择指标菜单,在过滤栏中输入 OpenCensus/task_latency_distribution,然后使用子菜单选择一个特定资源类型和指标:
    1. 活跃资源菜单中,选择您的受监控的资源。如果您在本地环境中运行该程序,请选择 Global
    2. 活跃指标类别菜单中,选择自定义
    3. 活跃指标菜单中,选择任务延迟时间分布
    4. 点击应用

以下屏幕截图显示了在本地环境中运行程序后收集到的时序:

Cloud Monitoring 中 OpenCensus 的指标。

热图中的每个条形代表程序的一次运行,而每个条形上的彩色部分代表延迟分布中的各个范围。

读取 Cloud Monitoring 中的 OpenCensus 指标

您可以使用用户定义的指标,包括由 OpenCensus 写入的指标,例如内置指标。您可以为自定义指标绘制图表、设置提醒、读取它们,也可以监控它们。

本部分介绍如何使用 API Explorer 读取指标数据。如需了解如何使用 Cloud 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"

现在,您已经拥有手动检索与指标类型关联的数据所需的信息。当您绘制指标图表时,Google Cloud 控制台中也会显示 type 字段的值。

检索指标数据

如需手动检索指标类型的时序数据,请执行以下操作:

  1. 转到 timeSeries.list 参考页面。
  2. 在参考页面上的试用此 API 微件中,填写以下字段:

    1. name 字段中输入您的项目名称:使用以下名称结构 projects/PROJECT_ID
    2. filter 字段中,输入以下值:

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

    3. 输入 interval.startTimeinterval.endTime 字段的值。输入的值必须是时间戳,例如 2018-10-11T15:48:38-04:00。确保 startTime 值早于 endTime 值。

    4. 点击执行按钮。

此类检索的结果如下所示:

    {
      "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,请参阅使用 API 创建用户定义的指标。实际上,OpenCensus Cloud Monitoring 导出器会为您使用此 API。 本部分详细介绍了 Cloud Monitoring 如何表示 OpenCensus 写入的指标。

OpenCensus API 使用的构造与 Cloud Monitoring 使用的构造不同,一些术语的使用也是如此。对于同一内容,在 Cloud Monitoring 中使用“指标”,而在 OpenCensus 中有时会使用“统计信息”。例如,将指标数据发送到 Cloud Monitoring 的 OpenCursus 组件称为“Stackdriver 统计信息导出器”。

如需简要了解 OpenCensus 指标模型,请参阅 OpenCensus 指标。

OpenCensus 统计信息数据模型与 Cloud Monitoring 指标数据模型之间并非整齐的一一映射。两种数据模型之间存在着许多相同概念,但这些概念不能直接相互换用。

  • OpenCensus 视图类似于 Monitoring API 中的 MetricDescriptor。该视图描述了如何收集和聚合各个测量结果。 所有记录的测量结果中均包含标记。

  • OpenCensus 标记是一个键值对。OpenCensus 标记通常对应于 Monitoring API 中的 LabelDescriptor。您可以使用标记来捕获相关上下文信息,以便对指标进行过滤和分组。

  • OpenCensus 度量描述了要记录的指标数据。 OpenCensus 聚合是对数据应用的函数,用于汇总数据。系统在导出数据时会使用这些函数来确定 Cloud Monitoring 指标描述符中报告的 MetricKindValueType 和单位。

  • OpenCensus 测量结果是收集的数据点。测量结果必须聚合到视图中。 否则,独立的测量结果将会被丢弃。OpenCensus 测量结果类似于 Monitoring API 中的 Point。测量结果聚合到视图中后,聚合数据将存储为视图数据,这类似于 Monitoring API 中的 TimeSeries

后续步骤