速習 Datadog APM

Kouhei Nagase

2022.12.8

Datadog APM を使った監視設計をすることがあり、使い勝手が良かったため基本的な部分と設定した方がいいなと思っている事項を書いていきます。

プロファイリング機能は使いませんでしたので、本記事では対象外です。

APM (Application Performance Management)

APM とは分散トレーシングとパフォーマンスを始めとしたその周辺データの管理と可視化を行うための機能です。例えば以下のようなデータを紐づけることができます。

  • エラー率
  • ログやメトリクス
  • レイテンシー
  • CPU・メモリの使用率

【用語】
Datadog APM における基本用語を簡単に説明します。

  • スパン: 1ロジックの開始・終了の実行時間を計測する単位。スパン同士は親子関係を持たせることができます
  • トレース: 複数のスパンを1つのリクエストとして取りまとめて計測する単位。トレースは1つ以上のスパンを含みます。
引用: https://qiita.com/muroon/items/ddda1f20c943dcd434c5

引用: https://docs.datadoghq.com/ja/tracing/

料金

https://www.datadoghq.com/ja/pricing/?product=apm–continuous-profiler#apm–continuous-profiler

基本はホスト単位での課金です。

  • APM: 31(年間コミット)、31(年間コミット)、36(オンデマンド)
    取り込み無料枠: 1ホスト/150GB
    Indexed Span 無料枠: 1ホスト/100万件
  • APM & Continuous Profiler: 40(年間コミット)、40(年間コミット)、48(オンデマンド)
    APMに含まれる無料枠
    プロファイル無料枠: 4コンテナ/1ホスト
  • 追加課金
    APMのスパン取り込み: $0.10/GB
    APMのスパン保存: $1.70/100万件(保存期間15日)
    プロファイルするコンテナ: $2/コンテナ
  • 料金監視のためのメトリクス
    datadog.estimated_usage.apm_hosts
    datadog.estimated_usage.apm.indexed_spans
    datadog.estimated_usage.apm.ingested_bytes
    datadog.estimated_usage.profiling.containers

スパイクに併せてスケールアウトしたり、アプリ実装が良からぬ方向に改修されたりすることで料金が跳ね上がる可能性があるので、これらメトリクスでパッと状況を見れるようにしておくことを推奨します。

セットアップ

Datadog agent 側

アプリ実装側

https://docs.datadoghq.com/ja/tracing/#datadog-%E3%81%B8%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%92%E9%80%81%E4%BF%A1
言語ごとにライブラリを使って設定します。
対応言語: Java/Python/Ruby/Go/NodeJS/PHP/C++/.NET Core/.NET Framework

今回は Go でのコードを例として取り上げます。

  • ライブラリ: https://github.com/DataDog/dd-trace-go
    基本的にサーバに併せてインポートして、インターセプター挿入するとよしなにやってくれます。
    よく使われる標準ライブラリやフレームワークはトレースを送るように追加実装されたものが提供されているため、まずはそれを活用してみるか openTelemetry使うことを推奨します。

gRPC サーバへの実装例

package main

import (
	"fmt"
	"net"

(中略)

	grpctrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/google.golang.org/grpc"
	"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func main() {

(中略)

	tracer.Start(
		tracer.WithEnv("dev"),
	)
	defer tracer.Stop()

	ddUnaryInterceptor := grpctrace.UnaryServerInterceptor(grpctrace.WithServiceName("web-service"))

	grpcServer := grpc.NewServer(
		grpcMiddleware.WithUnaryServerChain(
			ddUnaryInterceptor,
		),
	)
      grpc_health_v1.RegisterHealthServer(grpcServer, health.NewServer())
 
(中略)

 	err = grpcServer.Serve(lis)
 	if err != nil {
 		log.Fatalf("failed to serve: %v", err)
 	}
}

以下は MySQL でクエリをトレースする場合の実装例

package mysql

import (
(中略)
	"github.com/go-sql-driver/mysql"
	"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
	"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"

	sqltrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/database/sql"
)

func newConn() *Conn {
(中略)
	sqltrace.Register("mysql",
		&mysql.MySQLDriver{},
		sqltrace.WithServiceName("mysql-service"),
	)
	dsn := fmt.Sprintf(dsnFormat,
		c.MySQL.User,
		c.MySQL.Password,
		c.MySQL.Host,
		c.MySQL.Port,
		c.MySQL.DB,
	)

	conn, err := sqltrace.Open("mysql", dsn)
(中略)
}

func (conn *Conn) Get(ctx context.Context, query string, args ...interface{}) (row *sql.Row, err error) {
	span, ctx := tracer.StartSpanFromContext(ctx,
		"mysql-get",
		tracer.SpanType(ext.SpanTypeSQL),
		tracer.ServiceName("mysql-service"),
	)
	defer span.Finish(tracer.WithError(err))

	return conn.get(false, ctx, query, args...)
}

その他設定

この設定は入れておいた方がいいだろうということをいくつかご紹介します。

取り込み量のサンプリング

https://docs.datadoghq.com/tracing/trace_pipeline/ingestion_mechanisms/

データをサンプリングすることで無料枠を超過するのを防いだり、データの見通しをよくすることができます。

Datadog に送信・取り込みするかどうかはライブラリと agent で設定します。

設定は agent とライブラリでできますが、いずれも環境変数で設定することが推奨されています

agent で設定する場合

ライブラリで設定する場合

  • 各言語ごとの設定に従ってください
  • 大体の言語で以下の環境変数を設定することで実現できます
@env DD_TRACE_SAMPLE_RATE=0.1
@env DD_TRACE_SAMPLING_RULES=[{"service": `my-service`, "sample_rate": 0.5}]

トレースとログの紐付け

https://docs.datadoghq.com/ja/tracing/connect_logs_and_traces/

トレースとログを紐づけておくことで、トレースをもとに該当のログに素早くアクセスすることができるため調査や分析での効率がアップします。

負荷試験中のボトルネック調査やエラーログの調査の効率が上がるので併せて設定しておくことを推奨します。
言語ごとのライブラリの設定に従って実装することで実現できます。

Istio の通信可視化

https://docs.datadoghq.com/ja/tracing/setup_overview/proxy_setup/?tab=istio

Istio でサービスメッシュを組んでいる Kubernetes クラスタの場合は、トレーシングを設定することで、スパンの親子関係をよしなにやってくれるのでトレースの構築が楽になります。

また Data plane もスパンに含めて可視化することができます。
公式に沿って Istioインストール時に Tracing のフラグを立てるだけでした。

まとめ

分散システムを扱うことはごく当たり前になった昨今で監視やデバッグに必須の分散トレースですが、Datadog だと導入が比較的楽でかつ必要十分な機能を備えています。
ぜひ検討の候補に入れてみてはいがでしょうか?

ブログ一覧へ戻る

お気軽にお問い合わせください

SREの設計・技術支援から、
SRE運用内で使用する
ツールの導入など、
SRE全般についてご支援しています。

資料請求・お問い合わせ