dt-obs-analytics について
Dynatrace のスキルスクリプト群で、ダッシュボードやノートブックから DQL クエリを抽出し、Davis アナライザーで分析します。タイトルによる絞り込みや、分析期間・変数の指定に対応します。
主な機能
- 01ダッシュボードから DQL を抽出
- 02ノートブックから DQL を抽出
- 03タイトルまたは正規表現で絞り込み
- 04Davis アナライザーでクエリを分析
- 05期間と変数を指定
活用シーン
- 01指定したダッシュボードタイルのクエリ抽出
- 02ノートブック内のメトリクス異常分析
- 03複数クエリと主メトリクスの相関分析
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dynatrace/ dynatrace-for-ai --skill dt-obs-analyticsインストール後、Claude Code で/dt-obs-analyticsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
scripts/extract-timeseries-dashboard.jsextract-timeseries-notebook.jsrun-analyzer.js詳細
分析 — ダッシュボードとノートブックのクエリ抽出
scripts/ にある、プラットフォーム JavaScript スクリプト 3 つからなるパイプラインです。2 つの抽出スクリプトが、共通のアナライザーランナーにデータを渡します。
scripts/extract-timeseries-dashboard.js ──┐
scripts/extract-timeseries-notebook.js ──┴──► queryset.json ──► scripts/run-analyzer.js (any Davis analyzer)
各スクリプトは、次のように呼び出します。
dtctl exec function -f scripts/<script>.js --payload '<json>' -o json
-o json を指定すると、関数の戻り値は .result の下にラップされます。結果を確認する場合は、出力から直接読み取れるため、jq は必要ありません。出力全体を未加工のまま queries として run-analyzer.js に渡せば、自動的にラップを解除します。
ダッシュボード URL の解析
エントリーポイントが Dynatrace ダッシュボードの URL の場合は、スクリプトが必要とする 3 つの要素を抽出します。
https://<tenant>/ui/apps/dynatrace.dashboards/dashboard/<ID>#from=<from>&to=<to>&vfilter_<name>=<val>...
| URL の部分 | スクリプトでの格納先 |
|---|---|
/dashboard/ の後(# より前)のパスセグメント | extract-timeseries-dashboard.js のペイロード内の id |
#from= の値(%3A → : に URL デコード) | run-analyzer.js の timeframe.startTime(分析を実行する場合のみ必要) |
#to= の値(URL デコード) | run-analyzer.js の timeframe.endTime(分析を実行する場合のみ必要) |
vfilter_<name>=<value> パラメーター | run-analyzer.js の variables マップ(vfilter_ プレフィックスを削除) |
URL フラグメントの時間枠は、ダッシュボードの表示期間です。抽出された DQL に注入されることはありません。抽出スクリプトは、元の $variable トークンや、埋め込まれた | timeframe 句をそのまま含む DQL を返します。解析期間を設定するには、run-analyzer.js の呼び出し時に、解析した from/to の値を使用してください。ユーザーがクエリの一覧表示だけを希望している場合、時間枠は参考情報にすぎません。
注:run-analyzer.js に絶対値の timeframe.startTime(now... 式ではない値)を渡すと、解析前に DQL から埋め込まれた | timeframe ... ステージが削除されます。これにより、クエリにあらかじめ設定された期間ではなく、指定した期間がアナライザーに適用されます。相対値(now...)の期間では、埋め込まれた | timeframe はそのまま残ります。そのため、実際に解析されるクエリは抽出されたテキストと異なる場合があります。これは想定される動作です。指定した期間と結果が一致するよう、ここに記載しています。
簡単な bash での解析(純粋な bash と sed/awk を使用。python は不要です):
DASHBOARD_URL="https://abc123.apps.dynatrace.com/ui/apps/dynatrace.dashboards/dashboard/5bea16c7-029b-43b6-9735-459db2d25bbf#from=2026-05-28T04%3A00Z&to=2026-05-28T05%3A00Z&vfilter_host_group=prod&vfilter_workload=my-svc"
# Minimal URL-decoder: turn %XX into \xXX and let printf interpret it.
urldecode() { local s="${1//+/ }"; printf '%b' "${s//%/\\x}"; }
DOC_ID=$(echo "$DASHBOARD_URL" | sed 's/#.*//' | awk -F/ '{print $NF}')
FROM=$(urldecode "$(echo "$DASHBOARD_URL" | sed -n 's/.*[#&]from=\([^&]*\).*/\1/p')")
TO=$(urldecode "$(echo "$DASHBOARD_URL" | sed -n 's/.*[#&]to=\([^&]*\).*/\1/p')")
HOST_GROUP=$(echo "$DASHBOARD_URL" | sed -n 's/.*[#&]vfilter_host_group=\([^&]*\).*/\1/p')
WORKLOAD=$(echo "$DASHBOARD_URL" | sed -n 's/.*[#&]vfilter_workload=\([^&]*\).*/\1/p')
ノートブックの場合は、/notebook/ の後のパスセグメント、または /document/v0/#share=<ID> リンクの #share= の値を使用します。
手順 1 — クエリを抽出する
ダッシュボードから
# All tiles
dtctl exec function -f scripts/extract-timeseries-dashboard.js \
--payload '{"id":"<dashboard-id-or-name>"}' -o json
# Only tiles whose title matches a name the user mentioned (e.g. "CPU usage", "Kafka lag")
dtctl exec function -f scripts/extract-timeseries-dashboard.js \
--payload '{"id":"<dashboard-id>","titleFilter":"CPU usage"}' -o json
ユーザーが特定のタイル、チャート、またはセクションを指定した場合は、ダッシュボード全体を抽出するのではなく、その名前を titleFilter として渡します。titleFilter には、大文字と小文字を区別しない部分文字列、または /regex/flags パターンを指定できます。これにより、クエリセットを小さく絞り込めます。
ユーザーがどのタイルを希望しているか明確でない場合は、DQL をすべて抽出しないでください。ダッシュボードには 20~50 個のタイルが含まれることがあり、クエリをすべて返すとコンテキストが大幅に膨らみます。代わりに、次の 2 段階の手順を使用します。
listOnly: trueを指定してタイル名を一覧表示します(DQL は含まず、タイトルのみ)。dtctl exec function -f scripts/extract-timeseries-dashboard.js \ --payload '{"id":"<dashboard-id>","listOnly":true}' -o json # Returns: {"result":{"ok":true,"tiles":[{"id":"...","title":"CPU Usage","visualization":"lineChart"},...]}}- タイル名をユーザーに示し、どのタイルを指しているか尋ねます。
- 対象のタイルだけを
titleFilterで指定して再実行します。
これにより、関連するクエリが 1~2 件だけの場合に、20~50 件の DQL クエリをコンテキストに取り込まずに済みます。
ペイロードのオプション:
id(必須) — ダッシュボード ID(UUID)または正確な名前です。my.dynatrace.infraops.preview.*のようなプリセット ID も使用できます。titleFilter— 大文字と小文字を区別しない部分文字列("CPU usage")、または/regex/flags("/^kafka/i")です。listOnly—trueの場合、DQL を含めずにtiles: [{id, title, visualization}]を返します。対象の絞り込みに使用します。compact—trueの場合、タイルごとに{id, title, dqlQuery}のみを返します(description、visualization、isTimeseries を省略)。タイルあたりのトークン数を約 40% 削減します。listOnlyモードでは、visualization も省略します。includeSkipped—trueの場合、skipped[]配列全体を返します。デフォルトではskippedCountのみが返されます。
レスポンスのエンベロープ:
{
"ok": true,
"documentId": "...", "documentName": "...", "documentVersion": 7,
"queries": [
{ "id": "<tile-key>", "title": "...", "description": "...",
"dqlQuery": "timeseries avg(dt.host.cpu.usage)",
"visualization": "lineChart", "isTimeseries": true }
],
"skipped": [{ "id": "...", "reason": "non-data tile (markdown)" }]
}
失敗時:{ "ok": false, "error": { "code": "...", "message": "..." } }。
ノートブックから
エンベロープは同じですが、スキーマのたどり方が異なります。
# All cells
dtctl exec function -f scripts/extract-timeseries-notebook.js \
--payload '{"id":"<notebook-id-or-name>"}' -o json
# A specific section (if cell titles are set)
dtctl exec function -f scripts/extract-timeseries-notebook.js \
--payload '{"id":"<notebook-id>","titleFilter":"JVM memory"}' -o json
ノートブックのセルはタイトルが空の場合が多いため、特定のセルを指定する場合は、エンベロープ内の id で指定することをおすすめします。
ステップ 2 — アナライザーを実行する
抽出結果をファイルに保存し、シェル置換を使って渡します。シェルがファイルを読み込むため、JSON がモデルのコンテキストに入ることはありません。
# Run extractor, save output
dtctl exec function -f scripts/extract-timeseries-dashboard.js \
--payload '{"id":"<id>","titleFilter":"CPU usage","compact":true}' -o json > queryset.json
# Shell substitution: $(cat queryset.json) is expanded by the shell, not the model
dtctl exec function -f scripts/run-analyzer.js \
--payload '{
"analyzerName": "dt.statistics.NoveltyScoreAnalyzer",
"queries": '"$(cat queryset.json)"',
"timeframe": { "startTime": "...", "endTime": "..." },
"analyzerParams": { ... }
}' -o json
run-analyzer.js は {"result":{...}} 形式の dtctl エンベロープを自動的に展開します。保存した生の出力をそのまま渡してください。jq や解析の手順は不要です。配列/エンベロープ/dtctl 出力の形式は、スクリプト内で正規化されます。
大きなクエリーセット(タイルが多数ある場合)では、インラインの $(cat ...) 形式がシェルの引数長制限に達することがあります。その場合はペイロードファイルを作成し、dtctl の --data フラグを使ってください。引き続き jq は不要で、モデルのコンテキスト外で処理されます。
{ printf '{"analyzerName":"dt.statistics.NoveltyScoreAnalyzer","timeframe":{"startTime":"now-1h","endTime":"now"},"queries":'
cat queryset.json
printf '}'; } > payload.json
dtctl exec function -f scripts/run-analyzer.js --data payload.json -o json
run-analyzer.js の主なペイロード設定項目:
minScore— このしきい値を下回る結果を除外します(例:0.5)。スコアフィールドはnoveltyScore、anomalyScore、correlationCoefficient、correlation、coefficientから自動検出されます。上書きするにはscoreFieldを指定します。scoreField— スコアの読み取り元となるフィールド名を明示的に指定します(例:"noveltyScore")。
queries フィールドには、生の配列、抽出結果のエンベロープ({queries:[...]})、完全な dtctl 出力({"result":{"queries":[...]}})のいずれも指定できます。これら 3 つの形式はすべて自動的に正規化されます。
よく使われるアナライザー
| 目的 | analyzerName | analyzerParams |
|---|---|---|
| 異常なメトリクスを見つける | dt.statistics.anomaly_detection.SeasonalBaselineAnomalyDetectionAnalyzer | { "trainingTimeframe": { "startTime": "now-8d", "endTime": "now-1d" } }(省略可能) |
| 各メトリクスの新規性をスコア化する | dt.statistics.NoveltyScoreAnalyzer | { "detectionMode": "ALL", "minNoveltyScore": 0 }(省略可能) |
| 主メトリクスとの相関を調べる | dt.statistics.SimplePearsonCorrelationAnalyzer | 代わりに metricQuery を設定します(呼び出し形式が変わります) |
相関モード
metricQuery を渡すと、セット内の各クエリーを 1 つの主 DQL 文字列と相関させます。
dtctl exec function -f scripts/run-analyzer.js \
--payload '{
"analyzerName": "dt.statistics.SimplePearsonCorrelationAnalyzer",
"queries": '"$(cat queryset.json)"',
"metricQuery": "<dqlQuery of the primary tile, copied from extractor output>",
"timeframe": { "startTime": "...", "endTime": "..." }
}' -o json
前のアナライザー実行(例:異常検出 → 相関)に続けて実行する場合は、代わりに metricQueryFrom を使います。スクリプトが最も高いスコアの結果から dqlQuery を自動的に選択します。
dtctl exec function -f scripts/run-analyzer.js \
--payload '{
"analyzerName": "dt.statistics.SimplePearsonCorrelationAnalyzer",
"queries": '"$(cat queryset.json)"',
"metricQueryFrom": '"$(cat findings.json)"',
"timeframe": { "startTime": "...", "endTime": "..." }
}' -o json
両方が設定されている場合は、metricQuery が優先されます。
変数の置換
ダッシュボードクエリーには、URL の vfilter_* パラメーターに由来する $variable トークンが含まれていることがよくあります。実行前に置換するには、variables で渡してください。
dtctl exec function -f scripts/run-analyzer.js \
--payload '{
"analyzerName": "dt.statistics.anomaly_detection.SeasonalBaselineAnomalyDetectionAnalyzer",
"queries": [...],
"timeframe": { "startTime": "2026-05-28T04:00Z", "endTime": "2026-05-28T05:00Z" },
"variables": { "host_group": "prod", "workload": "my-svc" }
}' -o json
URL の vfilter_* パラメーターから vfilter_ プレフィックスを取り除き、variables を作成します。末尾の * ワイルドカードは自動的に取り除かれます。未解決のトークンはエラーになる形で残さず、DQL のフィルター句から削除されます。
レスポンスの形式
{
"ok": true,
"checkedAt": "...",
"analyzerName": "...",
"summary": { "checked": 12, "completed": 11, "errors": 1 },
"results": [
{
"id": "tile-key", "title": "CPU usage", "dqlQuery": "...",
"output": <raw analyzer output>,
"executionStatus": "COMPLETED"
}
],
"errors": [ { "id": "...", "error": "..." } ]
}
output フィールドには、アナライザーの生の結果が格納されます。アナライザーに応じて解釈してください。
- 異常検出:各出力エントリーの
anomalyScore、anomalies[]、またはraisedAlerts[]を確認します。スコアが 0.7 以上なら異常、0.4 以上なら境界域です。 - 新規性:
noveltyScore(または最も近いスコア形式の数値フィールド)を確認します。スコアが 0.7 以上なら新規性があります。 - 相関:
correlationCoefficientを確認します。|correlationCoefficient|の降順に並べ、|correlationCoefficient| < 0.5のエントリーを除外します。
エンドツーエンド:「このダッシュボードで異常なのは何か?」
# 1. Extract queries — shell reads file, JSON stays out of model context
dtctl exec function -f scripts/extract-timeseries-dashboard.js \
--payload '{"id":"5bea16c7-029b-43b6-9735-459db2d25bbf","compact":true}' \
-o json > queryset.json
# 2. Run anomaly detection — $(cat queryset.json) expanded by shell, not model
dtctl exec function -f scripts/run-analyzer.js \
--payload '{
"analyzerName": "dt.statistics.anomaly_detection.SeasonalBaselineAnomalyDetectionAnalyzer",
"queries": '"$(cat queryset.json)"',
"timeframe": { "startTime": "2026-05-28T04:00Z", "endTime": "2026-05-28T05:00Z" },
"variables": { "host_group": "prod", "workload": "my-svc" }
}' -o json > findings.json
# 3. Correlate — metricQueryFrom picks the top finding automatically
dtctl exec function -f scripts/run-analyzer.js \
--payload '{
"analyzerName": "dt.statistics.SimplePearsonCorrelationAnalyzer",
"queries": '"$(cat queryset.json)"',
"metricQueryFrom": '"$(cat findings.json)"',
"timeframe": { "startTime": "2026-05-28T04:00Z", "endTime": "2026-05-28T05:00Z" }
}' -o json
抽出した単一クエリーを検証する
抽出結果から dqlQuery フィールドを読み取り、そのまま渡します。
dtctl query --query "<dqlQuery copied from extractor output>" -o json | head -40
注意点
- ダッシュボードの生の JSON を自分で読み込まないでください。
dtctl get dashboard <id> -o jsonの出力は通常 50~200 KB です。抽出ツールはプラットフォーム上で JSON を読み込み、コンパクトなエンベロープ(約 5~15 KB)を返します。 - 必要なタイルが 1 つだけの場合は、すべてのタイルを抽出しないでください。 50 タイルのダッシュボードでは、50 個の DQL クエリがコンテキストに取り込まれます。ユーザーがタイルを指定した場合は、
titleFilterを使用してください。指定が曖昧な場合は、まずlistOnly: trueを使ってどのタイルかを確認し、そのタイルだけを抽出してください。 - フィルター付きのダッシュボードでは、変数の指定が必須です。
$variableトークンが置換されていないクエリでは、エンティティフィルターが暗黙に無視されます(例:in(field, $undefined)はtrueと評価されます)。URL にvfilter_*パラメーターがある場合は、必ずvariablesを渡してください。 - スキーマの変化。 タイルが理由
no DQL query foundとともにskippedに分類された場合、そのダッシュボードスキーマには抽出ツールが認識していないクエリの場所があります。スクリプトのpickQuery候補リストに追加してください。 - アナライザーの利用可否。 すべての Davis アナライザーが、すべてのテナントで利用できるわけではありません。呼び出しの結果が
Could not find an analyzer with name '...'またはis not a functionになった場合は、実際に登録されているアナライザーを一覧表示してください:dtctl get analyzers -o json。 - 統計的な代替処理は削除されています。
run-analyzer.jsは Davis アナライザーのみを呼び出します。過去の異常検知には、analyzerParamsで長いtrainingTimeframeを渡すか(例:{ "trainingTimeframe": { "startTime": "now-30d", "endTime": "now-1d" } })、DQL を直接クエリしてください。 - クエリ内のコメント。
// commentで始まる行を含むクエリは、抽出ツールによって正しく分類されます(timeseriesチェックの前に、先頭の行コメントやブロックコメントが削除されます)。
スクリプトのリファレンス
- scripts/extract-timeseries-dashboard.js — ダッシュボードから timeseries DQL を抽出します
- scripts/extract-timeseries-notebook.js — ノートブックに対して同様の処理を行います
- scripts/run-analyzer.js — 汎用的な Davis アナライザー実行ツールです