カスタム OpenMetrics チェックの書き方

カスタム OpenMetrics チェックの書き方

概要

ここでは、Kube DNS からタイミングメトリクスとステータスイベントを収集する簡単なチェックを例に挙げて、OpenMetricsBaseCheck インターフェイスの高度な使用方法について説明します。基本的な OpenMetrics チェックの構成については、Agent に関するドキュメントを参照してください。

高度な使用方法: OpenMetrics チェックインターフェイス

汎用のチェックより高度なチェック (たとえば、メトリクスの前処理) が必要な場合は、カスタム OpenMetricsBaseCheck を作成してください。これは汎用チェックの基本クラスです。Prometheus から公開されるメトリクス、イベント、サービスチェックを収集するための構造とヘルパーを提供します。このクラスに基づいてチェックを構成するには、少なくとも以下が必要です。

  • namespacemetrics マッピングを使用したデフォルトインスタンスの作成。
  • check() メソッドの実装 および/または
  • チェックで処理する OpenMetric メトリクスの名前を付けたメソッドの作成 (例: self.prometheus_metric_name)

カスタム Prometheus チェックの書き方

ここでは、簡単な Kube DNS チェックの記述例を示して、OpenMetricsBaseCheck クラスの使用方法について説明します。次の例は、以下の汎用 Prometheus チェックの機能を再現します。

instances:
  - prometheus_url: http://localhost:10055/metrics
    namespace: "kubedns"
    metrics:
      - kubedns_kubedns_dns_response_size_bytes: response_size.bytes
      - kubedns_kubedns_dns_request_duration_seconds: request_duration.seconds
      - kubedns_kubedns_dns_request_count_total: request_count
      - kubedns_kubedns_dns_error_count_total: error_count
      - kubedns_kubedns_dns_cachemiss_count_total: cachemiss_count

コンフィギュレーション

構成とチェックファイルは、名前が一致していなければなりません。チェックが mycheck.py という名前なら、構成ファイルは mycheck.yaml という名前にしなければなりません。

Prometheus チェックのコンフィギュレーションは、標準の Agent チェックとほぼ同じです。主な違いは、check.yaml ファイルに変数 prometheus_url を入れることです。conf.d/kube_dns.yaml は以下のようになります。

init_config:

instances:
    # Prometheus のメトリクスエンドポイントの URL
  - prometheus_url: http://localhost:10055/metrics

チェックの書き方

すべての OpenMetrics チェックは、OpenMetricsBaseCheck クラスを継承します。

from datadog_checks.base import OpenMetricsBaseCheck

class KubeDNSCheck(OpenMetricsBaseCheck):

メトリクスマッピングの定義

from datadog_checks.base import OpenMetricsBaseCheck

class KubeDNSCheck(OpenMetricsBaseCheck):
    def __init__(self, name, init_config, instances=None):
        METRICS_MAP = {
            #kubernetes 1.6.0 でメトリクスの名前が kubedns に変更されました
            'kubedns_kubedns_dns_response_size_bytes': 'response_size.bytes',
            'kubedns_kubedns_dns_request_duration_seconds': 'request_duration.seconds',
            'kubedns_kubedns_dns_request_count_total': 'request_count',
            'kubedns_kubedns_dns_error_count_total': 'error_count',
            'kubedns_kubedns_dns_cachemiss_count_total': 'cachemiss_count'
        }

デフォルトインスタンスの定義

デフォルトのインスタンスは、チェックに使用される基本コンフィギュレーションです。namespacemetricsprometheus_url をオーバーライドする必要があります。

OpenMetricsBaseCheck のコンフィギュレーションオプションの一部でもデフォルト値をオーバーライドするため、Prometheus と Datadog のメトリクスタイプの間ではメトリクス動作の関連性が増加します。

from datadog_checks.base import OpenMetricsBaseCheck

class KubeDNSCheck(OpenMetricsBaseCheck):
    def __init__(self, name, init_config, instances=None):
        METRICS_MAP = {
            #kubernetes 1.6.0 でメトリクスの名前が kubedns に変更されました
            'kubedns_kubedns_dns_response_size_bytes': 'response_size.bytes',
            'kubedns_kubedns_dns_request_duration_seconds': 'request_duration.seconds',
            'kubedns_kubedns_dns_request_count_total': 'request_count',
            'kubedns_kubedns_dns_error_count_total': 'error_count',
            'kubedns_kubedns_dns_cachemiss_count_total': 'cachemiss_count'
        }
        super(KubeDNSCheck, self).__init__(
            name,
            init_config,
            instances,
            default_instances={
                'kubedns': {
                    'prometheus_url': 'http://localhost:8404/metrics',
                    'namespace': 'kubedns',
                    'metrics': [METRIC_MAP],
                    'send_histograms_buckets': True,
                    'send_distribution_counts_as_monotonic': True,
                    'send_distribution_sums_as_monotonic': True,
                }
            },
            default_namespace='kubedns',
        )

check メソッドの実装

さらに機能を実装したい場合は、check() 関数をオーバーライドします。

instance から、メトリクスをポーリングするための Prometheus または OpenMetrics のメトリクスエンドポイント endpoint を使用します。

def check(self, instance):
    endpoint = instance.get('prometheus_url')
例外

不正なコンフィギュレーション、プログラミングエラー、メトリクスを収集できないなどの理由でチェックを実行できない場合は、わかりやすい例外を生成する必要があります。デバッグが容易になるように、この例外はログに記録され、Agent のステータスコマンドに表示されます。以下に例を示します。

$ sudo /etc/init.d/datadog-agent info

  Checks
  ======

    my_custom_check
    ---------------
      - instance #0 [ERROR]: Unable to find prometheus_url in config file.
      - Collected 0 metrics & 0 events

ConfigurationError を使用して check() メソッドを補強します。

from datadog_checks.base import ConfigurationError

def check(self, instance):
    endpoint = instance.get('prometheus_url')
    if endpoint is None:
        raise ConfigurationError("Unable to find prometheus_url in config file.")

次に、データを取得するとすぐにフラッシュします。

from datadog_checks.base import ConfigurationError

def check(self, instance):
    endpoint = instance.get('prometheus_url')
    if endpoint is None:
        raise ConfigurationError("Unable to find prometheus_url in config file.")

    self.process(instance)

ここまでのまとめ

from datadog_checks.base import ConfigurationError, OpenMetricsBaseCheck

class KubeDNSCheck(OpenMetricsBaseCheck):
    """
    Collect kube-dns metrics from Prometheus endpoint
    """
    def __init__(self, name, init_config, instances=None):
        METRICS_MAP = {
            #kubernetes 1.6.0 でメトリクスの名前が kubedns に変更されました
            'kubedns_kubedns_dns_response_size_bytes': 'response_size.bytes',
            'kubedns_kubedns_dns_request_duration_seconds': 'request_duration.seconds',
            'kubedns_kubedns_dns_request_count_total': 'request_count',
            'kubedns_kubedns_dns_error_count_total': 'error_count',
            'kubedns_kubedns_dns_cachemiss_count_total': 'cachemiss_count'
        }
        super(KubeDNSCheck, self).__init__(
            name,
            init_config,
            instances,
            default_instances={
                'kubedns': {
                    'prometheus_url': 'http://localhost:8404/metrics',
                    'namespace': 'kubedns',
                    'metrics': [METRIC_MAP],
                    'send_histograms_buckets': True,
                    'send_distribution_counts_as_monotonic': True,
                    'send_distribution_sums_as_monotonic': True,
                }
            },
            default_namespace='kubedns',
        )

    def check(self, instance):
        endpoint = instance.get('prometheus_url')
        if endpoint is None:
            raise ConfigurationError("Unable to find prometheus_url in config file.")

        self.process(instance)

さらに改良するには

Prometheus および OpenMetrics の基本インテグレーションに関する詳細は、インテグレーションのデベロッパ用ドキュメントをご参照ください。

追加のコンフィギュレーションオプションのデフォルト値を含めることで、OpenMetrics チェックをさらに改良できます。

ignore_metrics

メトリクスの一部は重複していたり、カーディナリティが非常に高くなるという理由で無視されます。このリストに含まれるメトリクスは、ログに Unable to handle metric というデバッグ行を残すことなく、暗黙にスキップされます。

labels_mapper

labels_mapper 辞書が提供されている場合は、ゲージの送信時に、labels_mapper 内のメトリクスラベルに対応する値がタグ名として使用されます。

exclude_labels

exclude_labels は、除外するラベルの配列です。除外されるラベルは、メトリクスの送信時にタグとして追加されません。

type_overrides

type_overrides は、Prometheus または OpenMetrics のメトリクス名をキーとし、メトリクスタイプ (文字列の名前) を値とする辞書です。これが、ペイロードにリストされているタイプの代わりに使用されます。タイプが指定されていないメトリクスにタイプを適用するために使用できます。 使用可能なタイプは countergaugesummaryuntypedhistogram です。

: この値は基本クラスでは空ですが、最終的なチェックではカスタムメトリクスとしてカウントされないように、オーバーロード/ハードコードする必要があります。

その他の参考資料