大量のメトリクスの送信
セキュリティモニタリングが使用可能です セキュリティモニタリングが使用可能です

大量のメトリクスの送信

DogStatsD には、アプリケーションから生成されるメトリクスを、転送プロトコルを介して Agent に送信するという機能があります。このプロトコルには UDP (User Datagram Protocol) または UDS (Unix Domain Socket) が使用されます。

DogStatsD を使用して大量のメトリクスを 1 つの Agent に送信する際、適切な措置を講じずに実行すると以下のような問題が発生する場合があります。

  • Agent の CPU 使用量の増加
  • データグラムやメトリクスのドロップ
  • DogStatsD クライアントライブラリ (UDS) により返されるエラー

これらの問題の大半は、以下で説明するようにコンフィギュレーションを調整することで軽減できます。

一般的な方法

Datadog 公式クライアントを使用する

すべての主要なプログラミング言語に対して Datadog が提供する公式 DogStatsD クライアントの最新バージョンを使用することをお勧めします。

クライアント側のバッファリングを有効にする

StatsD や DogStatsD のクライアントが、デフォルトで 1 つのデータグラムごとに 1 つのメトリクスを送信する場合がありますが、これによりクライアントやオペレーティングシステム、そして Agent のオーバーヘッドは非常に高くなります。複数のメトリクスを 1 つのダイアグラムにバッファリングできるようにクライアントを作成し、このオプションを有効にすることで問題を著しく改善できます。

DogStatsD が公式にサポートするクライアントの例をご紹介します。

デフォルトでは、Datadog の公式 Golang ライブラリ DataDog/datadog-go はバッファリングを使用します。各パケットのサイズとメッセージの数は、UDSUDP に異なるデフォルト値を使用します。クライアントコンフィギュレーションの詳細については、DataDog/datadog-go を参照してください。

package main

import (
        "log"
        "github.com/DataDog/datadog-go/statsd"
)

func main() {
  // この例では、メトリクスはデフォルトで UDP の正しいデフォルトコンフィギュレーションでバッファリングされます。
  statsd, err := statsd.New("127.0.0.1:8125")
  if err != nil {
    log.Fatal(err)
  }

  statsd.Gauge("example_metric.gauge", 1, []string{"env:dev"}, 1)
}

以下のコードブロックは、Datadog 公認の Python ライブラリである datadogpy を使用し、最大 25 のメトリクスを 1 つのパケットで送信するようバッファリングされた DogStatsD クライアントインスタンスを作成します。

from datadog import DogStatsd

with DogStatsd(host="127.0.0.1", port=8125, max_buffer_size=25) as batch:
    batch.gauge('example_metric.gauge_1', 123, tags=["environment:dev"])
    batch.gauge('example_metric.gauge_2', 1001, tags=["environment:dev"])

以下のコードブロックは、Datadog 公認の Ruby ライブラリである dogstatsd-ruby を使用し、複数のメトリクスを 1 つのパケットで送信するようバッファリングされた DogStatsD クライアントインスタンスを作成します。

require 'datadog/statsd'

statsd = Datadog::Statsd.new('127.0.0.1', 8125)

statsd.batch do |s|
  s.increment('example_metric.increment', tags: ['environment:dev'])
  s.gauge('example_metric.gauge', 123, tags: ['environment:dev'])
end

以下の例では、Datadog 公認の Java ライブラリである java-dogstatsd-client を使用して、最大のパケットサイズが 1500 バイトのバッファリングされた DogStatsD クライアントインスタンスを作成します。このクライアントインスタンスから送信されるメトリクスはすべてバッファリングされ、最大で 1500 パケット長のパッケージに入れて送信されます。

import com.timgroup.statsd.NonBlockingStatsDClient;
import com.timgroup.statsd.StatsDClient;
import java.util.Random;

public class DogStatsdClient {

    public static void main(String[] args) throws Exception {

        StatsDClient Statsd = new NonBlockingStatsDClientBuilder()
            .prefix("namespace").
            .hostname("127.0.0.1")
            .port(8125)
            .maxPacketSizeBytes(1500)
            .build();

        Statsd.incrementCounter("example_metric.increment", ["environment:dev"]);
        Statsd.recordGaugeValue("example_metric.gauge", 100, ["environment:dev"]);
    }
}

以下の例では、Datadog 公認の C# ライブラリである dogstatsd-csharp-client を使用し、UDP で転送を行う DogStatsD クライアントを作成します。

using StatsdClient;

public class DogStatsdClient
{
    public static void Main()
    {
        var dogstatsdConfig = new StatsdConfig
        {
            StatsdServerName = "127.0.0.1",
            StatsdPort = 8125,
        };

        using (var dogStatsdService = new DogStatsdService())
        {
            dogStatsdService.Configure(dogstatsdConfig);

            // カウンターとゲージは同じデータグラムで送信されます
            dogStatsdService.Counter("example_metric.count", 2, tags: new[] { "environment:dev" });
            dogStatsdService.Gauge("example_metric.gauge", 100, tags: new[] { "environment:dev" });
        }
    }
}

以下のコードブロックは、Datadog 公認の PHP ライブラリである php-datadogstatsd を使用し、複数のメトリクスを 1 つのパケットで送信するようバッファリングされた DogStatsD クライアントインスタンスを作成します。

<?php

require __DIR__ . '/vendor/autoload.php';

  use DataDog\BatchedDogStatsd;

$client = new BatchedDogStatsd(
  array('host' => '127.0.0.1',
          'port' => 8125,
     )
);

$client->increment('example_metric.increment', array('environment'=>'dev'));
$client->increment('example_metric.increment', $sampleRate->0.5 , array('environment'=>'dev'));

メトリクスのサンプリング

クライアント側でサンプリングレートの値を設定すると、DogStatsD クライアントから Agent へのトラフィックを減らすことができます。たとえば、サンプリングレートを 0.5 にすると、送信される UDP パケットの数が半減します。この方法には、トラフィックが減る代わりに精度や粒度がやや低下するという欠点もあります。

詳しい情報やコードの例が必要な場合は、DogStatsD の「サンプリングレート」パラメータの説明を参照してください。

UDS (Unix Domain Socket) を介した DogStatsD の使用

UDS は DogStatsD ペイロードの転送に使用される、プロセス間通信プロトコルです。UDP と比べてオーバーヘッドが非常に小さく、多くのシステムで DogStatsD のフットプリントを減らすことができます。

オペレーティングシステムのカーネルバッファ

ほとんどのオペレーティングシステムは、メトリクスを含むデータグラムを UDP や UDS を介して受信し、バッファに追加します。バッファにはサイズ制限があるため、その最大値に達すると、データグラムとその中に含まれるメトリクスがドロップを始めます。この最大値を調整すれば、受信したメトリクスを Agent が処理する時間を増やすことができます。

UDP (User Datagram Protocol) の場合

Linux

ほとんどの Linux ディストリビューションで、カーネル バッファの最大サイズはデフォルトで 212992(208 KB) に設定されています。これを確認するには、次のコマンドを使用します。

$ sysctl net.core.rmem_max
net.core.rmem_max = 212992

DogStatsD ソケットバッファの最大サイズを 25MB に設定するには、次を実行します。

sysctl -w net.core.rmem_max=26214400

これを永続的に変更するには、次のコンフィギュレーションを /etc/sysctl.conf に追加します。

net.core.rmem_max = 26214400

続いて、Agent の dogstatsd_so_rcvbuf コンフィギュレーションオプションを、datadog.yaml 内で同じ数値に設定します。

dogstatsd_so_rcvbuf: 26214400

Kubernetes で Agent または DogStatsD を開発している場合は、Kubernetes の sysctl に関するメモ セクションを参照してください。

UDS (Unix Domain Socket) 経由

Linux

UDS ソケットの場合、リーダーがライターより遅い場合、Linux はキュー内のデータグラムを内部的にバッファリングしています。このキューのサイズは、Linux がソケットごとにバッファリングするデータグラムの最大数を表します。この値は、次のコマンドで照会できます。

sysctl net.unix.max_dgram_qlen

値が 512 未満の場合は、次のコマンドを使用して 512 以上に増やすことができます。

sysctl -w net.unix.max_dgram_qlen=512

これを永続的に変更するには、次のコンフィギュレーションを /etc/sysctl.conf に追加します。

net.unix.max_dgram_qlen = 512

同様に、net.core.wmem_max を 4MiB に増やして、クライアントの書き込みパフォーマンスを向上させることができます。

net.core.wmem_max = 4194304

続いて、Agent の dogstatsd_so_rcvbuf コンフィギュレーションオプションを、datadog.yaml 内で同じ数値に設定します。

dogstatsd_so_rcvbuf: 4194304

Kubernetes の sysctl に関するメモ

Kubernetes を使用して Agent および/または DogStatsD をデプロイし、上記のように sysctl を構成する場合、その値の設定はコンテナごとに行う必要があります。ネームスペースを使用した net.* sysctl は、ポッドごとに設定できます。コンテナ内の sysctl へのアクセスを許可する方法や値の設定方法については、Kubernetes 公式ドキュメントを参照してください。

適切なパケットサイズを確保する

適切なサイズのパケットを Datadog Agent の DogStatsD サーバーに送信することにより、余分な CPU 使用を回避します。公式 DogStatsD クライアントの最新バージョンは、パフォーマンスに最適化されたサイズのパケットを送信します。

最新の Datadog DogStatsD クライアントのいずれかを使用している場合は、このセクションをスキップできます。

送信されたパケットが小さすぎる場合、Datadog Agent は複数を一緒にパックして、後でパイプラインでバッチ処理します。公式 DogStatsD クライアントは、メトリクスをグループ化して、パケットあたりのメトリクスの数の比率を最適化できます。

DogStatsD クライアントが dogstatsd_buffer_size のサイズのパケットを送信する場合、Datadog Agent が最も最適に動作します。パケットはバッファサイズより大きくしてはなりません。そうでない場合、Agent はパケットをバッファに完全にロードできず、一部のメトリクスが不正になります。DogStatsD クライアントの対応するコンフィギュレーションフィールドを使用します。

UDP に関する注意: UDP パケットは通常 Ethernet および IP レイヤーを通過するため、パケットサイズをネットワーク上の単一の Ethernet フレームよりも小さい値に制限することにより、IP パケットの断片化を回避します。ほとんどの場合、IPv4 ネットワークは 1500 バイトの MTU で構成されているため、この状況では送信パケットのパケットサイズを 1472 に制限する必要があります。

UDS に関する注意: 最高のパフォーマンスを得るには、UDS パケットのサイズが 8192 バイトである必要があります。

Agent の最大メモリ使用量を制限する

Agent は、DogStatsD クライアントから送信されたメトリクスのバーストを吸収しようとしますが、そのためには、メモリを使用する必要があります。これが短時間であり、このメモリが OS にすぐに解放された場合でも、スパイクが発生し、メモリ使用量の制限によりポッドまたはコンテナがエビクションされる可能性があるコンテナ化された環境で問題になる可能性があります。

アプリケーションでバーストでメトリクスを送信することは避けてください。これにより、Datadog Agent が最大メモリ使用量に達するのを防ぎます。

最大メモリ使用量を制限するために注意すべきもう 1 つのことは、バッファリングを減らすことです。Agent 内の DogStatsD サーバーのメインバッファは、dogstatsd_queue_size フィールドで構成できます (Datadog Agent 6.1.0 以降)。そのデフォルト値の 1024 は、およその最大メモリ使用量である 768MB を引き起こします。

: このバッファを減らすと、パケットドロップの数が増える可能性があります。

この例では、DogStatsD の最大メモリ使用量を約 384MB に減らします。

dogstatsd_queue_size: 512

クライアント側のテレメトリー

DogStatsD クライアントは、デフォルトでテレメトリーメトリクスを Agent に送信します。これを利用して、ボトルネックが存在する場合にトラブルシューティングを行うことができます。各メトリクスには、クライアントの言語とバージョンがタグ付けされます。これらのメトリクスはカスタムメトリクスとしてカウントされません。

以下のタグは、すべてのクライアントに共通してタグ付けされます。

タグ説明
clientクライアントの言語client:py
client_versionクライアントのバージョンclient_version:1.2.3
client_transportクライアントが使用する転送プロトコル (udp または uds)client_transport:uds

: UDP を使用すると、クライアントがネットワークエラーを検出できないため、バイトやパケットがドロップしてもメトリクスには反映されません。

バージョン 0.34.0 以降の Python クライアントが必要です。

メトリクス名メトリクスタイプ説明
datadog.dogstatsd.client.metricscountアプリケーションによって DogStatsD クライアントに送信された metrics の数 (サンプリング前)。
datadog.dogstatsd.client.eventscountアプリケーションによって DogStatsD クライアントに送信された events の数。
datadog.dogstatsd.client.service_checkscountアプリケーションによって DogStatsD クライアントに送信された service_checks の数。
datadog.dogstatsd.client.bytes_sentcountAgent に正常に送信されたバイト数。
datadog.dogstatsd.client.bytes_droppedcountDogStatsD クライアントによってドロップされたバイト数。
datadog.dogstatsd.client.packets_sentcountAgent に正常に送信されたデータグラムの数。
datadog.dogstatsd.client.packets_droppedcountDogStatsD クライアントによってドロップされたデータグラムの数。

テレメトリーを無効にするには、disable_telemetry メソッドを次のように使用します。

statsd.disable_telemetry()

クライアントコンフィギュレーションについて詳しくは、DataDog/datadogpy を参照してください。

バージョン 4.6.0 以降の Ruby クライアントが必要です。

メトリクス名メトリクスタイプ説明
datadog.dogstatsd.client.metricscountアプリケーションによって DogStatsD クライアントに送信された metrics の数 (サンプリング前)。
datadog.dogstatsd.client.eventscountアプリケーションによって DogStatsD クライアントに送信された events の数。
datadog.dogstatsd.client.service_checkscountアプリケーションによって DogStatsD クライアントに送信された service_checks の数。
datadog.dogstatsd.client.bytes_sentcountAgent に正常に送信されたバイト数。
datadog.dogstatsd.client.bytes_droppedcountDogStatsD クライアントによってドロップされたバイト数。
datadog.dogstatsd.client.packets_sentcountAgent に正常に送信されたデータグラムの数。
datadog.dogstatsd.client.packets_droppedcountDogStatsD クライアントによってドロップされたデータグラムの数。

テレメトリーを無効にするには、 disable_telemetry パラメーターを true に設定します。

Datadog::Statsd.new('localhost', 8125, disable_telemetry: true)

クライアントコンフィギュレーションについて詳しくは、DataDog/dogstatsd-ruby を参照してください。

バージョン 3.4.0 以降の Go クライアントが必要です。

メトリクス名メトリクスタイプ説明
datadog.dogstatsd.client.metricscountアプリケーションによって DogStatsD クライアントに送信された metrics の数 (サンプリング前)。
datadog.dogstatsd.client.eventscountアプリケーションによって DogStatsD クライアントに送信された events の数。
datadog.dogstatsd.client.service_checkscountアプリケーションによって DogStatsD クライアントに送信された service_checks の数。
datadog.dogstatsd.client.bytes_sentcountAgent に正常に送信されたバイト数。
datadog.dogstatsd.client.bytes_droppedcountDogStatsD クライアントによってドロップされたバイト数。
datadog.dogstatsd.client.bytes_dropped_queuecountDogStatsD クライアントのキューが一杯だったためにドロップされたバイト数。
datadog.dogstatsd.client.bytes_dropped_writercountDatadog への書き込みでエラーが起きたためにドロップされたバイト数。
datadog.dogstatsd.client.packets_sentcountAgent に正常に送信されたデータグラムの数。
datadog.dogstatsd.client.packets_droppedcountDogStatsD クライアントによってドロップされたデータグラムの数。
datadog.dogstatsd.client.packets_dropped_queuecountDogStatsD クライアントのキューが一杯だったためにドロップされたデータグラムの数。
datadog.dogstatsd.client.packets_dropped_writercountDatadog への書き込みでエラーが起きたためにドロップされたデータグラムの数。
datadog.dogstatsd.client.metric_dropped_on_receivecount内部受信チャンネルがいっぱいであるためにドロップされたメトリクスの数 (WithChannelMode() を使用している場合のみ)。バージョン 3.6.0 以降の Go クライアントが必要です。

テレメトリーを無効にするには、WithoutTelemetry を次のように設定します。

statsd, err: = statsd.New("127.0.0.1:8125", statsd.WithoutTelemetry())

クライアントコンフィギュレーションについて詳しくは、DataDog/datadog-go を参照してください。

バージョン 2.10.0 以降の Java クライアントが必要です。

メトリクス名メトリクスタイプ説明
datadog.dogstatsd.client.metricscountアプリケーションによって DogStatsD クライアントに送信された metrics の数 (サンプリング前)。
datadog.dogstatsd.client.eventscountアプリケーションによって DogStatsD クライアントに送信された events の数。
datadog.dogstatsd.client.service_checkscountアプリケーションによって DogStatsD クライアントに送信された service_checks の数。
datadog.dogstatsd.client.bytes_sentcountAgent に正常に送信されたバイト数。
datadog.dogstatsd.client.bytes_droppedcountDogStatsD クライアントによってドロップされたバイト数。
datadog.dogstatsd.client.packets_sentcountAgent に正常に送信されたデータグラムの数。
datadog.dogstatsd.client.packets_droppedcountDogStatsD クライアントによってドロップされたデータグラムの数。
datadog.dogstatsd.client.packets_dropped_queuecountDogStatsD クライアントのキューが一杯だったためにドロップされたデータグラムの数。

テレメトリーを無効にするには、enableTelemetry(false) ビルダーオプションを使用します。

StatsDClient client = new NonBlockingStatsDClientBuilder()
    .hostname("localhost")
    .port(8125)
    .enableTelemetry(false)
    .build();

クライアントコンフィギュレーションについて詳しくは、DataDog/java-dogstatsd-client を参照してください。

PHP クライアントのバージョン 1.5.0 以降、テレメトリーは BatchedDogStatsd クライアントに対してデフォルトで有効になり、DogStatsd クライアントに対してデフォルトで無効になります。

メトリクス名メトリクスタイプ説明
datadog.dogstatsd.client.metricscountアプリケーションによって DogStatsD クライアントに送信された metrics の数 (サンプリング前)。
datadog.dogstatsd.client.eventscountアプリケーションによって DogStatsD クライアントに送信された events の数。
datadog.dogstatsd.client.service_checkscountアプリケーションによって DogStatsD クライアントに送信された service_checks の数。
datadog.dogstatsd.client.bytes_sentcountAgent に正常に送信されたバイト数。
datadog.dogstatsd.client.bytes_droppedcountDogStatsD クライアントによってドロップされたバイト数。
datadog.dogstatsd.client.packets_sentcountAgent に正常に送信されたデータグラムの数。
datadog.dogstatsd.client.packets_droppedcountDogStatsD クライアントによってドロップされたデータグラムの数。

テレメトリーを有効または無効にするには、disable_telemetry 引数を使用します。DogStatsd クライアントでテレメトリーを使用すると、ネットワークの使用量が大幅に増加するので注意してください。テレメトリーを使用する場合は、BatchedDogStatsd を使用することをお勧めします。

DogStatsd クライアントで有効にするには

use DataDog\DogStatsd;

$statsd = new DogStatsd(
    array('host' => '127.0.0.1',
          'port' => 8125,
          'disable_telemetry' => false,
      )
  );

BatchedDogStatsd クライアントでテレメトリーを無効にするには

use DataDog\BatchedDogStatsd;

$statsd = new BatchedDogStatsd(
    array('host' => '127.0.0.1',
          'port' => 8125,
          'disable_telemetry' => true,
      )
  );

クライアントコンフィギュレーションについて詳しくは、DataDog/php-datadogstatsd を参照してください。

バージョン 5.0.0 以降の .NET クライアントが必要です。

メトリクス名メトリクスタイプ説明
datadog.dogstatsd.client.metricscountアプリケーションによって DogStatsD クライアントに送信された metrics の数 (サンプリング前)。
datadog.dogstatsd.client.eventscountアプリケーションによって DogStatsD クライアントに送信された events の数。
datadog.dogstatsd.client.service_checkscountアプリケーションによって DogStatsD クライアントに送信された service_checks の数。
datadog.dogstatsd.client.bytes_sentcountAgent に正常に送信されたバイト数。
datadog.dogstatsd.client.bytes_droppedcountDogStatsD クライアントによってドロップされたバイト数。
datadog.dogstatsd.client.packets_sentcountAgent に正常に送信されたデータグラムの数。
datadog.dogstatsd.client.packets_droppedcountDogStatsD クライアントによってドロップされたデータグラムの数。
datadog.dogstatsd.client.packets_dropped_queuecountDogStatsD クライアントのキューが一杯だったためにドロップされたデータグラムの数。

テレメトリーを無効にするには、TelemetryFlushIntervalnull に設定します。

var dogstatsdConfig = new StatsdConfig
{
    StatsdServerName = "127.0.0.1",
    StatsdPort = 8125,
};

// テレメトリーを無効にする
dogstatsdConfig.Advanced.TelemetryFlushInterval = null;

クライアントコンフィギュレーションについて詳しくは、DataDog/dogstatsd-csharp-client を参照してください。

その他の参考資料