大量のメトリクスの送信
Datadog の調査レポート: サーバーレスの状態 レポート: サーバーレスの状態

大量のメトリクスの送信

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

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

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

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

一般的な方法

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

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

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

以下の例では、Datadog 公認の Golang ライブラリである datadog-go を使用して、最大 256 のメトリクスをバッファリングできる DogStatsD クライアントを作成します。このクライアントインスタンスから送信されるメトリクスはすべてバッファリングされ、最大で 256 のメトリクスを含むパッケージに入れて送信されます。

package main

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

func main() {

  statsd, err := statsd.New("127.0.0.1:8125",
                 statsd.Buffered(),
                 statsd.WithMaxMessagesPerPayload(256),
                )
    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 を使用して、最大 256 のメトリクスをバッファリングできる DogStatsD クライアントを作成します。このクライアントインスタンスから送信されるメトリクスはすべてバッファリングされ、最大で 256 のメトリクスを含むパッケージに入れて送信されます。

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 NonBlockingStatsDClient("namespace", "127.0.0.1", 8125, 256);

        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()
    {
      StatsdUDP udp = new StatsdUDP("127.0.0.1", 8125);

      // "udp" で転送を行う stats インスタンスを作成
      Statsd s = new Statsd(udp);
      s.Add<Statsd.Counting,int>("example_metric.count", 1, tags: new[] {"environment:dev"});
      s.Add("event title", "content", priority: "low");
      s.Add<Statsd.Counting,int>("example_metric.count", 1, tags: new[] {"environment:dev"});

      // この呼び出しの前にバッファリングされた全メトリクスが 1 つのパケットで送信される
      s.Send();
    }
}

以下のコードブロックは、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

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

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 への書き込みでエラーが起きたためにドロップされたデータグラムの数。

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

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

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

テレメトリーは間もなく Java クライアントに追加されます。

テレメトリーは間もなく PHP クライアントに追加されます。

テレメトリーは間もなく .NET クライアントに追加されます。

その他の参考資料