オブザーバビリティの玄関口!DataDog Agentを使ったGoアプリのメトリクス送信サンプルコード
[go, monitoring, metrics]というヒントがありますが、DataDog Agentの主な役割はズバリ何でしょう?
| 選択肢 | 答え |
| A | ソースコードの自動生成 |
| B | アプリケーションやインフラの監視とメトリクスの収集 |
| C | ビルドパイプラインの高速化 |
正解は… B!
DataDog Agentは、サーバー、コンテナ、アプリケーションの環境にインストールされ、そこからメトリクス(性能指標)、トレース(リクエストの流れ)、ログといったあらゆるデータを収集し、DataDogプラットフォームに送信する監視の「玄関口」となるソフトウェアです。ソフトウェアエンジニアにとっては、「自分のコードが本番環境でどう動いているか」を知るための目であり耳となります。
DataDog Agentが収集するデータは、エンジニアの皆さんが抱えるさまざまな課題を解決してくれます。
アプリケーションのレイテンシ(遅延)やCPU使用率などのメトリクスを収集することで、「なぜこのAPIは遅いのか?」「どこでリソースを食っているのか?」を具体的に特定できます。
エラーログや異常なメトリクス(例
エラーレートの急上昇)を即座にDataDogに送信。アラートを設定することで、ユーザーが気付く前に問題を検知し、トレース機能でコードレベルの原因特定がグッと容易になります。
サーバーのメモリやディスク使用率を監視し、過剰にリソースを割り当てている部分を見つけられます。結果として、インフラのコスト削減にも貢献します。
アプリケーション(Goで書かれたAPIなど)のメトリクスだけでなく、その下のOS、Kubernetes、データベースといったインフラ全体のデータを一つのダッシュボードで統合的に見ることができます。
DataDog Agentの導入は非常に簡単で、環境に合わせて様々な方法があります。
DataDogの公式サイトでアカウントを作成し、提供されるAPIキーを用意します。
インストールスクリプトの実行
LinuxやmacOSの場合、通常は提供されるワンライナーのシェルスクリプトを実行するだけです。
(セキュリティ上の理由から、具体的なスクリプトはここでは割愛しますが、公式サイトで最新のものが提供されます)
設定ファイルの確認
インストール後、設定ファイル datadog.yaml が作成されます。ここで、APIキーなどを設定します。
# /etc/datadog-agent/datadog.yaml の一部
api_key: <あなたのDataDog APIキー>
# ... その他の設定(ホスト名など)
Agentの起動
sudo systemctl start datadog-agent (Linuxの場合) などでサービスを起動します。
現在では、コンテナ環境での利用が主流です。
| 環境 | 導入方法 | ポイント |
| Docker | 公式Dockerイメージをdocker runで実行 | ホストのネットワークやプロセスにアクセスするための権限設定が必要 |
| Kubernetes | 公式のHelm ChartやDaemonSetを使用 | 各ノードにAgentをデプロイし、クラスタ全体を監視 |
DataDog Agentが「インフラ」のメトリクス(CPU使用率など)を自動で収集してくれる一方で、「アプリケーション固有」のメトリクス(例ログイン成功回数、処理キューの長さ)は、エンジニアがコード内に記述して送信する必要があります。
DataDog Agentは、様々なライブラリを通じてメトリクスを受け取れますが、ここではDataDogが推奨するメトリクス送信ライブラリの一つである go-datadog-metrics (goconsensus/go-datadog-metrics) を使ったGo言語の例を見てみましょう。(DataDog AgentはGo言語で開発されていますが、アプリケーションはどの言語でも大丈夫です!)
このサンプルでは、アプリ内の「特定のエンドポイントが呼ばれた回数」を計測し、DataDog Agentに送信します。
コードの準備 (Go)
package main
import (
"log"
"net/http"
"time"
"github.com/DataDog/datadog-go/statsd" // DataDog Agentへの送信ライブラリ
)
var statsdClient *statsd.Client
func init() {
// DataDog AgentはデフォルトでUDPポート8125でStatsDプロトコルをリッスンしています
// 実際にはエラーハンドリングが必要です
client, err := statsd.New("127.0.0.1:8125")
if err != nil {
log.Fatal(err)
}
statsdClient = client
}
func myHandler(w http.ResponseWriter, r *http.Request) {
// 1. メトリクスの送信
// "api.homepage.hits" という名前のカウンターを1増やす
statsdClient.Incr("api.homepage.hits", nil, 1)
// 2. タグを付けて送信(重要!)
// どの環境(env)のどのバージョン(version)から来たリクエストかタグ付け
tags := []string{"env:production", "version:1.2.0"}
statsdClient.Gauge("api.response_time_ms", float64(time.Since(time.Now())), tags, 1)
w.WriteHeader(http.StatusOK)
w.Write([]byte("Hello, DataDog!"))
}
func main() {
http.HandleFunc("/", myHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
動作の解説
statsd.New("127.0.0.1:8125") で、ローカルで動いているDataDog Agent(デフォルトでStatsDプロトコルを受け付けている)に接続します。
statsdClient.Incr(...) は、カウンターメトリクスをインクリメントします。
statsdClient.Gauge(...) は、現在の値(この例ではレスポンスタイム)を送信します。
タグ (tags) を付けることで、「どの環境」「どのバージョン」のデータか分類でき、DataDogのダッシュボードで絞り込みやグループ化が可能になり、デバッグ効率が劇的に向上します。
この仕組みにより、エンジニアは自分のアプリケーションの心臓部で何が起こっているかをリアルタイムで確認し、常に改善していくことができるのです!