代理中的自定义指标

本指南介绍如何配置 Monitoring 代理以识别您的应用指标并将其导出到 Cloud Monitoring。

Monitoring 代理是一个 collectd 守护进程。除了将许多预定义的系统和第三方指标导出到 Cloud Monitoring 之外,该代理还可以将您自己 collectd 应用指标作为自定义指标导出到 Monitoring。您的 collectd 插件也可以导出到 Monitoring。

将应用指标导出到 Monitoring 的另一种方法是使用 StatsD。Cloud Monitoring 提供将 StatsD 指标映射到自定义指标的默认配置。如果您对该映射感到满意,则不需要执行下述自定义步骤。如需了解详情,请参阅 StatsD 插件

如果您不熟悉 Monitoring 的自定义指标,请参阅指标,时间序列和资源时间序列的结构使用自定义指标

准备工作

  • 在虚拟机实例上安装最新的 Monitoring 代理,并验证其是否正常工作。要更新您的代理,请参阅更新代理

  • 配置 collectd,以便从应用中获得监控数据。 Collectd 通过其读取插件支持多个应用框架和标准监控端点。找到适合您的读取插件。

  • (可选)为方便起见,您可以将代理的 collectd 参考文档添加到您系统的 man 页面,方法是更新 MANPATH 变量并运行 mandb

    export MANPATH="$MANPATH:/opt/stackdriver/collectd/share/man"
        sudo mandb
        

    手册页面适用于 stackdriver-collectd

重要文件和目录

通过安装代理创建的以下文件和目录与使用 Monitoring 代理 (collectd) 相关:

/etc/stackdriver/collectd.conf

代理使用的 collectd 配置文件。请修改此文件以更改常规配置。

/etc/stackdriver/collectd.d/

用户添加的配置文件的目录。要通过代理发送自定义指标,您应该将下方讨论的所需配置文件置于此目录中。为了实现向后兼容性,代理还会在 /opt/stackdriver/collectd/etc/collectd.d/ 中查找文件。

/opt/stackdriver/collectd/share/man/*

代理的 collectd 版本的文档。您可以将这些页面添加到系统的一组 man 页面;如需了解详情,请参阅准备工作

/etc/init.d/stackdriver-agent

代理的 init 脚本。

Monitoring 如何处理 collectd 指标

在后台,Monitoring 代理会处理 collectd 指标并将其发送到 Monitoring,Monitoring 会将每个指标视为以下类别中的一个:

  • 自定义指标。系统会将具有元数据键 stackdriver_metric_type 和单一数据源的 collectd 指标作为自定义指标处理,并使用 Monitoring API 中的 projects.timeSeries.create 方法发送至 Monitoring。

  • 特选指标。所有其他 collectd 指标都是通过内部 API 发送到 Monitoring 的。仅接受和处理精选指标列表中的指标。

  • 舍弃的指标。不在精选指标列表中且不是自定义指标的 collectd 指标将被 Monitoring 以静默方式舍弃。代理本身不知道哪些指标被接受或被舍弃。

通过代理写入自定义指标

您要配置代理,以将指标数据点发送到 Monitoring。每个数据点必须与一个您通过指标描述符定义的自定义指标关联。如需简要了解这些概念,请参阅指标,时间序列和资源;如需详细了解这些概念,请参阅时间序列的结构使用自定义指标

您可以将该 collectd 指标视为自定义指标,只需向该指标添加适当的元数据即可:

  • stackdriver_metric_type:(必填)导出的指标的名称。示例:custom.googleapis.com/my_custom_metric

  • label:[LABEL]:(可选)导出指标的附加标签。例如,如果您想要一个名为 color 的 Monitoring STRING 标签,则您的元数据键将为 label:color,该键的值可以是 "blue"。每个指标类型最多可以有 10 个标签。

您可以使用 collectd 过滤条件链来修改指标的元数据。由于过滤条件链无法修改数据源列表,且自定义指标仅支持单一数据源,因此您想要与 collectd 过滤条件链一同使用的 collectd 指标必须具备单一数据源。

示例

在此示例中,我们将监控来自两个 Nginx 服务(my_service_amy_service_b)的活动 Nginx 连接。我们将使用自定义指标将这些连接发送到 Monitoring。具体步骤如下:

  1. 识别每个 Nginx 服务的 collectd 指标。

  2. 定义 Monitoring 指标描述符。

  3. 配置 collectd 过滤条件链,将元数据添加到 collectd 指标,以满足 Monitoring 代理的期望。

传入的 collectd 指标

Collectd 预计指标将由以下组件组成:前五个组件构成指标的 collectd 标识符

        Host, Plugin, Plugin-instance, Type, Type-instance, [value]
    

在本例中,您想要作为自定义指标发送的指标具有以下值:

组件 预期值
主机 任何
插件 curl_json
插件实例 nginx_my_service_a
nginx_my_service_b1
类型 gauge
类型实例 active-connections
[value] 任意值2

备注
1 在此示例中,该值对应用(Nginx)和已连接服务的名称进行编码。
2 该值通常是一个时间戳,且是双精度数字。Monitoring 负责处理关于解读各类值的详细信息。Monitoring 代理目前不支持复合值。

Monitoring 指标描述符和时间序列

在 Monitoring 中,为您的自定义指标设计指标描述符。以下描述符是本示例中数据的合理选择:

  • 姓名:custom.googleapis.com/nginx/active_connections
  • 标签:
    • service_name(STRING):与 Nginx 关联的服务的名称。
  • 种类:GAUGE
  • 类型:DOUBLE

设计好指标描述符后,您可以使用 projects.metricDescriptors.create 进行创建,也可以借助时间序列元数据自动创建(如下文所述)。如需了解详情,请参阅此页面中的创建指标描述符

鉴于指标描述符的定义方式,该指标描述符的时间序列数据必须包含以下信息:

  • 指标名称:custom.googleapis.com/nginx/active_connections
  • 指标标签值:
    • service_name"my_service_a""my_service_b"

对于所有指标,代理会自动获取其他时间序列信息,包括相关联的受监控资源(发送数据的虚拟机实例)和指标的数据点。您无需执行任何特殊操作。

您的过滤条件链

创建一个文件,/opt/stackdriver/collectd/etc/collectd.d/nginx_curl_json.conf,其中包含以下代码:

LoadPlugin match_regex
    LoadPlugin target_set
    LoadPlugin target_replace

    # Insert a new rule in the default "PreCache" chain, to divert your metrics.
    PreCacheChain "PreCache"
    <Chain "PreCache">
      <Rule "jump_to_custom_metrics_from_curl_json">
        # If the plugin name and instance match, this is PROBABLY a metric we're looking for:
        <Match regex>
          Plugin "^curl_json$"
          PluginInstance "^nginx_"
        </Match>
        <Target "jump">
          # Go execute the following chain; then come back.
          Chain "PreCache_curl_json"
        </Target>
      </Rule>
      # Continue processing metrics in the default "PreCache" chain.
    </Chain>

    # Following is a NEW filter chain, just for your metric.
    # It is only executed if the default chain "jumps" here.
    <Chain "PreCache_curl_json">

      # The following rule does all the work for your metric:
      <Rule "rewrite_curl_json_my_special_metric">
        # Do a careful match for just your metrics; if it fails, drop down
        # to the next rule:
        <Match regex>
          Plugin "^curl_json$"                   # Match on plugin.
          PluginInstance "^nginx_my_service_.*$" # Match on plugin instance.
          Type "^gauge$"                         # Match on type.
          TypeInstance "^active-connections$"    # Match on type instance.
        </Match>

        <Target "set">
          # Specify the metric descriptor name:
          MetaData "stackdriver_metric_type" "custom.googleapis.com/nginx/active_connections"
          # Specify a value for the "service_name" label; clean it up in the next Target:
          MetaData "label:service_name" "%{plugin_instance}"
        </Target>

        <Target "replace">
          # Remove the "nginx_" prefix in the service_name to get the real service name:
          MetaData "label:service_name" "nginx_" ""
        </Target>
      </Rule>

      # The following rule is run after rewriting your metric, or
      # if the metric wasn't one of your custom metrics. The rule returns to
      # the default "PreCache" chain. The default processing
      # will write all metrics to Cloud Monitoring,
      # which will drop any unrecognized metrics: ones that are not
      # in the list of curated metrics and do not have
      # the custom metric metadata.
      <Rule "go_back">
        Target "return"
      </Rule>
    </Chain>
    

加载新配置

通过在虚拟机实例上执行以下命令,重启您的代理以选择新配置:

sudo service stackdriver-agent restart
    

您的自定义指标信息将开始传输至 Monitoring。

参考和最佳做法

指标描述符和时间序列

如需了解 Cloud Monitoring 指标,请参阅指标、时间序列和资源。如需了解详情,请参阅使用自定义指标时间序列结构

指标描述符。指标描述符包含以下重要组成部分:

  • 名称,格式为 custom.googleapis.com/[NAME1]/.../[NAME0]。例如:

    custom.googleapis.com/my_measurement
        custom.googleapis.com/instance/network/received_packets_count
        custom.googleapis.com/instance/network/sent_packets_count
        

    自定义指标名称必须以 custom.googleapis.com/ 开头。建议采用层次化命名,使指标更易于跟踪。指标名称不能包含连字符;如需了解确切的命名规则,请参阅命名指标类型和标签

  • 最多 10 个标签,用于为指标数据添加注释,例如 device_namefault_typeresponse_code。标签的值不在指标描述符中指定。

  • 数据点的种类和类型,如“double 类型的 gauge 值”。如需了解详情,请参阅 MetricKindValueType

时间序列。指标数据点具备以下重要部分:

  • 关联的指标描述符的名称。

  • 所有指标描述符标签的值。

  • 与指标描述符的类型和种类一致的带时间戳的值。

  • 数据所属的受监控的资源,通常是虚拟机实例。该资源的空间是内置的,因此描述符不需要单独的标签。

创建指标描述符

您不必提前创建指标描述符。 当数据点到达 Monitoring 时,系统可使用该数据点的指标名称、标签和值自动创建 gauge 或 cumulative 指标描述符。如需了解详情,请参阅自动创建自定义指标

不过,自行创建指标描述符具有以下优势:

  • 您可以为指标及其标签添加一些周到的文档。

  • 您可以指定其他指标种类和类型。代理仅支持种类与类型的以下组合:(GAUGE, DOUBLE) 和 (CUMULATIVE, INT64)。如需了解详情,请参阅指标种类和值类型

  • 您可以指定除 STRING 以外的标签类型。

如果您将使用未定义指标名称的数据点写入 Monitoring,则系统为该数据点创建新的指标描述符。如果您正在对写入指标数据的代码进行调试,这可能会造成问题:指标名称拼写错误将产生虚假的指标描述符。

在您创建指标描述符后,或者系统为您创建指标描述符后,该指标描述符便无法更改。例如,您无法添加或移除标签。您只能删除指标描述符(此操作将删除其所有数据),然后以您想要的方式重新创建描述符。

如需详细了解如何创建指标描述符,请参阅定义指标

费用和限制

Cloud Monitoring 会根据收到的指标数据量对 collectd 指标(用户定义指标和代理指标)收费。如需了解详情,请参阅 Google Cloud 操作套件的价格

除价格外,Cloud Monitoring 对每个 GCP 项目中的指标时间序列数量和用户定义的指标描述符数量有限制。如需了解详情,请参阅配额和限制

如果您发现已创建不再需要的指标描述符,可以使用 Monitoring API 查找和删除描述符。如需了解详情,请参阅 projects.metricDescriptors

问题排查

本部分介绍如何配置 Monitoring 代理的 write_log 插件以输出整套数据点,包括元数据。此方法可用于确定需要转换的数据点,并确保您的转换按预期方式进行。

启用 write_log

write_log 插件包含在 stackdriver-agent 程序包中。要启用该插件,请执行以下操作:

  1. root 身份修改以下配置文件:

    /etc/stackdriver/collectd.conf
        
  2. LoadPlugin write_gcm 之后添加:

    LoadPlugin write_log
        
  3. <Plugin "write_gcm">…</Plugin> 之后添加:

    <Plugin "write_log">
          Format JSON
        </Plugin>
        
  4. 搜索 <Target "write">…</Target>,每 Plugin "write_gcm" 之后添加:

    Plugin "write_log"
        
  5. 保存更改并重启代理:

    sudo service stackdriver-agent restart
        

这些更改将为报告的每个指标值(包括完整的 collectd 标识符、元数据条目和值)打印一行日志。

write_log 的输出

如果您成功完成上一步,则应该会在系统日志中看到 write_log 的输出:

  • 基于 Debian 的 Linux/var/log/syslog
  • 基于 Red Hat 的 Linux/var/log/messages

在本文中,为了更便于您阅读,我们对以下几行示例内容的格式进行了设置。

Dec  8 15:13:45 test-write-log collectd[1061]: write_log values:#012[{
        "values":[1933524992], "dstypes":["gauge"], "dsnames":["value"],
        "time":1481210025.252, "interval":60.000,
        "host":"test-write-log.c.test-write-log.internal",
        "plugin":"df", "plugin_instance":"udev", "type":"df_complex", "type_instance":"free"}]

    Dec  8 15:13:45 test-write-log collectd[1061]: write_log values:#012[{
        "values":[0], "dstypes":["gauge"], "dsnames":["value"],
        "time":1481210025.252, "interval":60.000,
        "host":"test-write-log.c.test-write-log.internal",
        "plugin":"df", "plugin_instance":"udev", "type":"df_complex", "type_instance":"reserved"}]