LLMベースのAgentをセルフホストで動かしていると、「どのプロンプトが何トークン消費して、レスポンスに何ミリ秒かかったか」 を把握したくなる。そういうときのためにDatadogにはLLM Observability機能があるが、ドキュメントを読むと「Datadog Agentを入れろ」「コードにdd-traceを組み込め」と書いてある。
自分の環境にはDockerもなく、Datadog Agent CLIも入れたくない。しかも対象アプリのソースは触りたくない——という状況で、systemdの環境変数だけで完結する方法を見つけたので共有する。
環境
| 項目 | 内容 |
|---|---|
| OS | Ubuntu 24.04 Server(ローカル、GKEクラスタとは別) |
| Node.js | v24.13.0(nvm管理) |
| 対象アプリ | OpenClaw(systemd user serviceで常駐) |
| Datadog Site | us5.datadoghq.com |
| 制約 | Docker不可・Datadog Agent CLI不可 |
方針:Agentless + Auto-instrumentation
dd-traceはOpenAIなどのSDKに対して自動插桩(Auto-instrumentation)ができる。Datadog Agentを使わないAgentlessモードにすれば、dd-traceが直接HTTPSでDatadog APIにデータを送ってくれる。
つまり:
- アプリのコードは一切変更しない
- Datadog Agentはインストールしない
- systemdの設定だけで完結する
実装手順
1. dd-traceをグローバルインストール
対象アプリがグローバルパッケージとして動いているため、dd-traceも合わせてグローバルにインストールする。
npm install -g dd-trace
インストール先のパスを確認しておく(後で使う)。
npm root -g
# 例: /home/youruser/.nvm/versions/node/v24.13.0/lib/node_modules
2. systemd service ファイルを編集する
ここが核心。Node.jsの--importフラグを使い、アプリ起動前にdd-traceを初期化させる。
systemctl --user edit --full your-app.service
[Service]セクションに以下を追記する:
[Service]
# --- Datadog LLM Observability ---
# (1) アプリ起動前にdd-traceをimportする
# ※ ESMモードでは必ず絶対パスのfile:// URLで指定すること(後述)
Environment="NODE_OPTIONS=--import file:///home/youruser/.nvm/versions/node/v24.13.0/lib/node_modules/dd-trace/initialize.mjs"
# (2) LLM ObservabilityとAgentlessモードを有効化
Environment=DD_LLMOBS_ENABLED=1
Environment=DD_LLMOBS_AGENTLESS_ENABLED=1
# (3) アプリ情報とDatadog Siteを設定
Environment=DD_LLMOBS_ML_APP=your-app-name
Environment=DD_SITE=us5.datadoghq.com
# (4) サービスタグの統一
Environment=DD_SERVICE=your-service-name
Environment=DD_ENV=production
Environment=DD_VERSION=1.0.0
# (5) API Keyは環境変数ファイルから読み込む(平文で書かない)
EnvironmentFile=/home/youruser/secrets/.env
セキュリティ補足:
DD_API_KEY=xxxxを.envファイルに書いてEnvironmentFileで読み込む理由は、systemctl statusでプロセス情報を見られたときにキーが露出しないようにするため。
3. リロードして再起動
systemctl --user daemon-reload
systemctl --user restart your-app
ログでdd-traceが初期化されていることを確認できれば完了。あとはDatadogのLLM Observabilityダッシュボードを開くと、プロンプトとレスポンスの内容、トークン数、レイテンシがすべて見えるようになる。
ハマりポイント:Node.js v24のESMはNODE_PATHを無視する
最初、こういう設定を試みた:
Environment=NODE_PATH=/home/youruser/.nvm/versions/node/v24.13.0/lib/node_modules
Environment="NODE_OPTIONS=--import dd-trace/initialize.mjs"
これでサービスを起動すると ERR_MODULE_NOT_FOUND で即死する。
原因:Node.js v24のESM Loaderは、NODE_PATHを参照しない。CommonJSと違い、ESMは「裸のパッケージ名(bare specifier)」でグローバルディレクトリを解決できない仕様になっている。
解決策:--importには絶対パスのfile:// URLを渡す。
# ✅ これが正解
Environment="NODE_OPTIONS=--import file:///home/youruser/.nvm/versions/node/v24.13.0/lib/node_modules/dd-trace/initialize.mjs"
長いが、これしかない。
ハマりポイント②:しばらくするとデータが途絶える(SSL証明書エラー)
設定直後はDatadogのダッシュボードにデータが届いているのに、しばらくするとパタッと止まる——という現象に遭遇した。
何が起きていたか
dd-traceにはLLMデータの送信チャネルとは別に、instrumentation telemetry(ライブラリ自身の使用統計)を送る内部モジュールがある。このモジュールがAgentlessモード下でtelemetry-intake.us5.datadoghq.comに接続しようとした際、自己署名証明書を使ってくるため、Node.js v24がDEPTH_ZERO_SELF_SIGNED_CERTエラーで接続を拒否する。
このSSL失敗が繰り返されるうちにdd-traceの内部状態が劣化し、最終的にLLMObsのデータパイプラインまで道連れで止まる、という挙動だった。
修正:2つの環境変数を追加で無効化する
# dd-trace自身の使用統計テレメトリを無効化(LLMデータ送信には影響しない)
Environment=DD_INSTRUMENTATION_TELEMETRY_ENABLED=false
# ローカルのDatadog Agent(ポート8126)への接続試行を無効化
Environment=DD_REMOTE_CONFIGURATION_ENABLED=false
教訓
ローカルにDatadog Agentが存在しないAgentless構成では、この2つを最初から無効化しておくべきだった。DD_LLMOBS_AGENTLESS_ENABLED=1を設定してもdd-trace内部の別チャネルが存在し、それらは独立して動いている。Agentlessだからといって「Agent前提の通信」が完全に消えるわけではない。
まとめ
| 今回の方法 | |
|---|---|
| アプリのコード変更 | なし |
| Datadog Agent インストール | なし |
| Docker / 重量級ミドルウェア | なし |
| 観測できる情報 | プロンプト・レスポンス・トークン数・レイテンシ |
Agentlessモード × systemd環境変数 × ESM絶対パス指定、この3点が揃えばLLM Observabilityは意外とシンプルに実現できる。同じ環境(nvm + systemd user service + ESMアプリ)で詰まっている人の参考になれば。