dt-obs-analytics
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAnalytics — Dashboard & Notebook Query Extraction
分析功能——仪表板与笔记本查询提取
A pipeline of three platform JavaScript scripts under — two extractors feeding a shared analyzer runner:
scripts/scripts/extract-timeseries-dashboard.js ──┐
scripts/extract-timeseries-notebook.js ──┴──► queryset.json ──► scripts/run-analyzer.js (any Davis analyzer)Each script is invoked via:
bash
dtctl exec function -f scripts/<script>.js --payload '<json>' -o json-o json.resultjqqueriesrun-analyzer.jsscripts/scripts/extract-timeseries-dashboard.js ──┐
scripts/extract-timeseries-notebook.js ──┴──► queryset.json ──► scripts/run-analyzer.js (任意Davis分析器)每个脚本通过以下方式调用:
bash
dtctl exec function -f scripts/<script>.js --payload '<json>' -o json-o json.resultjqqueriesrun-analyzer.jsParsing a dashboard URL
解析仪表板URL
When the entry point is a Dynatrace dashboard URL, extract the three components the scripts need:
https://<tenant>/ui/apps/dynatrace.dashboards/dashboard/<ID>#from=<from>&to=<to>&vfilter_<name>=<val>...| URL part | Script destination |
|---|---|
Path segment after | |
| |
| |
| |
The timeframe in the URL fragment is the dashboard's display window. It is not injected into the extracted DQL — the extractor returns the DQL verbatim with its original tokens and any embedded clauses intact. Use the parsed / values only when calling to set the analysis window. If the user just wants to list the queries, the timeframe is informational only.
$variable| timeframefromtorun-analyzer.jsNote: when you pass an absolute (not a expression), it strips any embedded stage from the DQL before analysis, so the analyzer honors your requested window rather than the query's baked-in one. For relative () windows the embedded is left intact. This means the query actually analyzed can differ from the extracted text — expected behavior, noted here so results line up with the window you asked for.
run-analyzer.jstimeframe.startTimenow...| timeframe ...now...| timeframeQuick bash parse (pure bash + sed/awk — no python needed):
bash
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"当入口为Dynatrace仪表板URL时,提取脚本所需的三个组件:
https://<tenant>/ui/apps/dynatrace.dashboards/dashboard/<ID>#from=<from>&to=<to>&vfilter_<name>=<val>...| URL部分 | 脚本目标参数 |
|---|---|
| |
| |
| |
| |
URL片段中的时间范围是仪表板的显示窗口。它不会被注入到提取的DQL中——提取器会原样返回带有原始标记和任何嵌入子句的DQL。仅在调用设置分析窗口时使用解析后的/值。如果用户只是想列出查询,时间范围仅作为参考信息。
$variable| timeframerun-analyzer.jsfromto注意:当你向传递绝对(而非表达式)时,它会在分析前从DQL中移除任何嵌入的阶段,这样分析器会遵循你请求的窗口,而非查询中内置的窗口。对于相对()窗口,嵌入的会被保留。这意味着实际分析的查询可能与提取的文本不同——这是预期行为,在此说明以便结果与你要求的窗口一致。
run-analyzer.jstimeframe.startTimenow...| timeframe ...now...| timeframe快速bash解析(纯bash + sed/awk — 无需python):
bash
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.
简易URL解码器:将%XX转换为\xXX,让printf解析。
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')
For notebooks: path segment after `/notebook/`, or `#share=` value for `/document/v0/#share=<ID>` links.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=`值。Step 1 — Extract queries
步骤1 — 提取查询
From a dashboard
从仪表板提取
bash
undefinedbash
undefinedAll tiles
所有面板
dtctl exec function -f scripts/extract-timeseries-dashboard.js
--payload '{"id":"<dashboard-id-or-name>"}' -o json
--payload '{"id":"<dashboard-id-or-name>"}' -o json
dtctl exec function -f scripts/extract-timeseries-dashboard.js
--payload '{"id":"<dashboard-id-or-name>"}' -o json
--payload '{"id":"<dashboard-id-or-name>"}' -o json
Only tiles whose title matches a name the user mentioned (e.g. "CPU usage", "Kafka lag")
仅提取标题与用户提及名称匹配的面板(例如"CPU usage"、"Kafka lag")
dtctl exec function -f scripts/extract-timeseries-dashboard.js
--payload '{"id":"<dashboard-id>","titleFilter":"CPU usage"}' -o json
--payload '{"id":"<dashboard-id>","titleFilter":"CPU usage"}' -o json
**When the user names a specific tile, chart, or section**, pass its name as `titleFilter` rather than extracting the full dashboard. `titleFilter` is a case-insensitive substring or `/regex/flags` pattern. This keeps the queryset small and focused.
**When it is not clear which tile(s) the user wants**, do NOT extract all DQL — dashboards can have 20–50 tiles and returning all queries causes significant context bloat. Instead use a two-step flow:
1. List tile names with `listOnly: true` (no DQL, just titles):
```bash
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"},...]}}- Show the tile names to the user and ask which tile(s) they mean.
- Re-run with for only the tile(s) of interest.
titleFilter
This avoids pulling 20–50 DQL queries into context when only 1–2 are relevant.
Payload knobs:
- (required) — dashboard ID (UUID) or exact name. Preset IDs like
idwork.my.dynatrace.infraops.preview.* - — case-insensitive substring (
titleFilter) or"CPU usage"(/regex/flags)."/^kafka/i" - — when
listOnly, returnstruewithout DQL. Use for disambiguation.tiles: [{id, title, visualization}] - — when
compact, returns onlytrueper tile (drops description, visualization, isTimeseries). Saves ~40% per-tile tokens. In{id, title, dqlQuery}mode, drops visualization too.listOnly - — when
includeSkipped, returns the fulltruearray. Default: onlyskipped[]is returned.skippedCount
Response envelope:
json
{
"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)" }]
}On failure: .
{ "ok": false, "error": { "code": "...", "message": "..." } }dtctl exec function -f scripts/extract-timeseries-dashboard.js
--payload '{"id":"<dashboard-id>","titleFilter":"CPU usage"}' -o json
--payload '{"id":"<dashboard-id>","titleFilter":"CPU usage"}' -o json
**当用户指定特定面板、图表或区域时**,将其名称作为`titleFilter`传递,而非提取整个仪表板。`titleFilter`是不区分大小写的子字符串或`/regex/flags`模式。这样可以保持查询集小巧且聚焦。
**当不清楚用户需要哪些面板时**,请勿提取所有DQL——仪表板可能包含20–50个面板,返回所有查询会导致上下文严重冗余。请改用两步流程:
1. 使用`listOnly: true`列出面板名称(无DQL,仅标题):
```bash
dtctl exec function -f scripts/extract-timeseries-dashboard.js \
--payload '{"id":"<dashboard-id>","listOnly":true}' -o json
# 返回结果:{"result":{"ok":true,"tiles":[{"id":"...","title":"CPU Usage","visualization":"lineChart"},...]}}- 向用户展示面板名称,询问他们需要哪些面板。
- 使用重新运行,仅提取感兴趣的面板。
titleFilter
这样可以避免在只需要1–2个查询时,将20–50个DQL查询带入上下文。
Payload参数:
- (必填)——仪表板ID(UUID)或确切名称。预设IDs如
id可正常使用。my.dynatrace.infraops.preview.* - ——不区分大小写的子字符串(
titleFilter)或"CPU usage"(/regex/flags)。"/^kafka/i" - ——设为
listOnly时,返回true,不包含DQL。用于消除歧义。tiles: [{id, title, visualization}] - ——设为
compact时,每个面板仅返回true(移除描述、可视化类型、isTimeseries)。可减少约40%的面板令牌数。在{id, title, dqlQuery}模式下,还会移除可视化类型。listOnly - ——设为
includeSkipped时,返回完整的true数组。默认仅返回skipped[]。skippedCount
响应结构:
json
{
"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": "..." } }From a notebook
从笔记本提取
Same envelope, different schema walk:
bash
undefined响应结构相同,但遍历的schema不同:
bash
undefinedAll cells
所有单元格
dtctl exec function -f scripts/extract-timeseries-notebook.js
--payload '{"id":"<notebook-id-or-name>"}' -o json
--payload '{"id":"<notebook-id-or-name>"}' -o json
dtctl exec function -f scripts/extract-timeseries-notebook.js
--payload '{"id":"<notebook-id-or-name>"}' -o json
--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
--payload '{"id":"<notebook-id>","titleFilter":"JVM memory"}' -o json
Notebook cells often have empty titles — prefer addressing cells by `id` from the envelope if targeting a specific one.dtctl exec function -f scripts/extract-timeseries-notebook.js
--payload '{"id":"<notebook-id>","titleFilter":"JVM memory"}' -o json
--payload '{"id":"<notebook-id>","titleFilter":"JVM memory"}' -o json
笔记本单元格通常没有标题——如果要定位特定单元格,优先使用响应结构中的`id`。Step 2 — Run an analyzer
步骤2 — 运行分析器
Save the extractor output to a file, then pass it via shell substitution — the shell reads the file, so the JSON never enters the model's context:
bash
undefined将提取器输出保存到文件,然后通过shell替换传递——shell会读取文件,因此JSON不会进入模型上下文:
bash
undefinedRun extractor, save output
运行提取器,保存输出
dtctl exec function -f scripts/extract-timeseries-dashboard.js
--payload '{"id":"<id>","titleFilter":"CPU usage","compact":true}' -o json > queryset.json
--payload '{"id":"<id>","titleFilter":"CPU usage","compact":true}' -o json > queryset.json
dtctl exec function -f scripts/extract-timeseries-dashboard.js
--payload '{"id":"<id>","titleFilter":"CPU usage","compact":true}' -o json > queryset.json
--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
Shell替换:$(cat queryset.json)由shell展开,而非模型
dtctl exec function -f scripts/run-analyzer.js
--payload '{ "analyzerName": "dt.statistics.NoveltyScoreAnalyzer", "queries": '"$(cat queryset.json)"', "timeframe": { "startTime": "...", "endTime": "..." }, "analyzerParams": { ... } }' -o json
--payload '{ "analyzerName": "dt.statistics.NoveltyScoreAnalyzer", "queries": '"$(cat queryset.json)"', "timeframe": { "startTime": "...", "endTime": "..." }, "analyzerParams": { ... } }' -o json
`run-analyzer.js` unwraps the `{"result":{...}}` dtctl envelope automatically — pass the raw saved output as-is. No `jq` or parsing step is needed: normalization of the array / envelope / dtctl-output shapes happens inside the script.
For large querysets (many tiles), the inline `$(cat ...)` form can hit shell argument-length limits. Build the payload file and use dtctl's `--data` flag instead — still no `jq` and still out of model context:
```bash
{ 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 jsonKey payload knobs for :
run-analyzer.js- — drop results below this threshold (e.g.
minScore). Auto-detects score field from0.5,noveltyScore,anomalyScore,correlationCoefficient,correlation. Passcoefficientto override.scoreField - — explicit field name to read score from (e.g.
scoreField)."noveltyScore"
The field accepts any of: a raw array, the extractor envelope (), or the full dtctl output (). All three are normalized automatically.
queries{queries:[...]}{"result":{"queries":[...]}}dtctl exec function -f scripts/run-analyzer.js
--payload '{ "analyzerName": "dt.statistics.NoveltyScoreAnalyzer", "queries": '"$(cat queryset.json)"', "timeframe": { "startTime": "...", "endTime": "..." }, "analyzerParams": { ... } }' -o json
--payload '{ "analyzerName": "dt.statistics.NoveltyScoreAnalyzer", "queries": '"$(cat queryset.json)"', "timeframe": { "startTime": "...", "endTime": "..." }, "analyzerParams": { ... } }' -o json
`run-analyzer.js`会自动解包`{"result":{...}}`格式的dtctl响应——直接传递保存的原始输出即可。无需`jq`或解析步骤:脚本内部会自动对数组、响应结构、dtctl输出格式进行标准化。
对于大型查询集(多个面板),内联`$(cat ...)`形式可能会达到shell参数长度限制。请构建payload文件并使用dtctl的`--data`标志——仍然无需`jq`,且不会进入模型上下文:
```bash
{ 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 jsonrun-analyzer.js- ——丢弃低于此阈值的结果(例如
minScore)。会自动从0.5、noveltyScore、anomalyScore、correlationCoefficient、correlation中检测分数字段。可传递coefficient来覆盖。scoreField - ——读取分数的显式字段名称(例如
scoreField)。"noveltyScore"
queries{queries:[...]}{"result":{"queries":[...]}}Common analyzers
常用分析器
| Goal | analyzerName | analyzerParams |
|---|---|---|
| Find anomalous metrics | | |
| Score how novel each metric is | | |
| Correlate against a primary metric | | set |
| 目标 | analyzerName | analyzerParams |
|---|---|---|
| 查找异常指标 | | |
| 计算每个指标的新颖性评分 | | |
| 与主指标进行关联 | | 改为设置 |
Correlation mode
关联模式
Pass to correlate every query in the set against a single primary DQL string:
metricQuerybash
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 jsonWhen chaining from a previous analyzer run (e.g. anomaly detection → correlation), use instead. The script picks the highest-scored result's automatically:
metricQueryFromdqlQuerybash
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 jsonmetricQuery传递,将查询集中的每个查询与单个主DQL字符串进行关联:
metricQuerybash
dtctl exec function -f scripts/run-analyzer.js \
--payload '{
"analyzerName": "dt.statistics.SimplePearsonCorrelationAnalyzer",
"queries": '"$(cat queryset.json)"',
"metricQuery": "<从提取器输出复制的主面板dqlQuery>",
"timeframe": { "startTime": "...", "endTime": "..." }
}' -o json当从之前的分析器运行结果链式调用时(例如异常检测 → 关联),请改用。脚本会自动选择得分最高的结果的:
metricQueryFromdqlQuerybash
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如果同时设置了和,优先。
metricQuerymetricQueryFrommetricQueryVariable substitution
变量替换
Dashboard queries often contain tokens (from URL params). Pass them via to substitute before execution:
$variablevfilter_*variablesbash
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 jsonBuild from URL params by stripping the prefix. Trailing wildcards are stripped automatically. Unresolved tokens are cleaned up from DQL filter clauses rather than left to error.
variablesvfilter_*vfilter_*仪表板查询通常包含标记(来自URL的参数)。通过传递这些变量,在执行前进行替换:
$variablevfilter_*variablesbash
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的参数构建。末尾的通配符会被自动去除。未解析的标记会从DQL过滤子句中清除,而非保留导致错误。
vfilter_vfilter_*variables*Response shape
响应格式
json
{
"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": "..." } ]
}The field is the raw analyzer result. Interpret it based on the analyzer:
output- Anomaly detection: look for ,
anomalyScore, oranomalies[]in each output entry. Score ≥ 0.7 → abnormal, ≥ 0.4 → borderline.raisedAlerts[] - Novelty: look for (or the closest score-like numeric field). Score ≥ 0.7 → novel.
noveltyScore - Correlation: look for . Sort by
correlationCoefficientdescending; drop entries where|correlationCoefficient|.|correlationCoefficient| < 0.5
json
{
"ok": true,
"checkedAt": "...",
"analyzerName": "...",
"summary": { "checked": 12, "completed": 11, "errors": 1 },
"results": [
{
"id": "tile-key", "title": "CPU usage", "dqlQuery": "...",
"output": <原始分析器输出>,
"executionStatus": "COMPLETED"
}
],
"errors": [ { "id": "...", "error": "..." } ]
}output- 异常检测:在每个输出条目中查找、
anomalyScore或anomalies[]。评分≥0.7 → 异常,≥0.4 → 临界。raisedAlerts[] - 新颖性评分:查找(或最接近的类分数数字字段)。评分≥0.7 → 新颖。
noveltyScore - 关联分析:查找。按
correlationCoefficient降序排序;丢弃|correlationCoefficient|的条目。|correlationCoefficient| < 0.5
End-to-end: "what's abnormal on this dashboard?"
端到端流程:“这个仪表板有什么异常?”
bash
undefinedbash
undefined1. Extract queries — shell reads file, JSON stays out of model context
1. 提取查询——shell读取文件,JSON不会进入模型上下文
dtctl exec function -f scripts/extract-timeseries-dashboard.js
--payload '{"id":"5bea16c7-029b-43b6-9735-459db2d25bbf","compact":true}'
-o json > queryset.json
--payload '{"id":"5bea16c7-029b-43b6-9735-459db2d25bbf","compact":true}'
-o json > queryset.json
dtctl exec function -f scripts/extract-timeseries-dashboard.js
--payload '{"id":"5bea16c7-029b-43b6-9735-459db2d25bbf","compact":true}'
-o json > queryset.json
--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
2. 运行异常检测——$(cat queryset.json)由shell展开,而非模型
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
--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
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
--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
3. 关联分析——metricQueryFrom自动选择得分最高的结果
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
--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
undefineddtctl 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
--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
undefinedVerifying a single extracted query
验证单个提取的查询
Read the field from the extractor output and pass it directly:
dqlQuerybash
dtctl query --query "<dqlQuery copied from extractor output>" -o json | head -40从提取器输出中读取字段并直接传递:
dqlQuerybash
dtctl query --query "<从提取器输出复制的dqlQuery>" -o json | head -40Gotchas
注意事项
- Never read raw dashboard JSON yourself. is typically 50–200 KB. The extractor reads it on the platform and returns a compact envelope (~5–15 KB).
dtctl get dashboard <id> -o json - Never extract all tiles when only one is needed. A 50-tile dashboard returns 50 DQL queries into context. If the user names a tile, use . If it's ambiguous, use
titleFilterfirst to ask which tile — then extract only that one.listOnly: true - Variables are required for filtered dashboards. Queries with unsubstituted tokens silently drop entity filters (e.g.
$variableevaluates toin(field, $undefined)). Always passtruewhen the URL hasvariablesparams.vfilter_* - Schema drift. If a tile lands in with reason
skipped, the dashboard schema has a query location the extractor doesn't know about — add it to theno DQL query foundcandidate list in the script.pickQuery - Analyzer availability. Not all Davis analyzers are available on every tenant. If a call comes back with or
Could not find an analyzer with name '...', list what's actually registered:is not a function.dtctl get analyzers -o json - Statistical fallback removed. only calls Davis analyzers. For historical anomaly detection, pass a long
run-analyzer.jsviatrainingTimeframe(e.g.analyzerParams), or query the DQL directly.{ "trainingTimeframe": { "startTime": "now-30d", "endTime": "now-1d" } } - Comments in queries. Queries starting with lines are classified correctly by the extractor (leading line/block comments are stripped before the
// commentcheck).timeseries
- 切勿自行读取原始仪表板JSON。通常为50–200 KB。提取器会在平台上读取它并返回紧凑的响应结构(约5–15 KB)。
dtctl get dashboard <id> -o json - 切勿在仅需要一个面板时提取所有面板。包含50个面板的仪表板会返回50个DQL查询到上下文中。如果用户指定了面板名称,请使用。如果存在歧义,请先使用
titleFilter询问用户需要哪个面板——然后仅提取该面板。listOnly: true - 过滤后的仪表板需要变量。带有未替换标记的查询会静默删除实体过滤器(例如
$variable会被评估为in(field, $undefined))。当URL包含true参数时,务必传递vfilter_*。variables - Schema漂移。如果某个面板因原因被列入
no DQL query found,说明仪表板schema存在提取器未知的查询位置——请将其添加到脚本中的skipped候选列表中。pickQuery - 分析器可用性。并非所有Davis分析器在每个租户上都可用。如果调用返回或
Could not find an analyzer with name '...',请列出实际注册的分析器:is not a function。dtctl get analyzers -o json - 已移除统计回退。仅调用Davis分析器。对于历史异常检测,请通过
run-analyzer.js传递较长的analyzerParams(例如trainingTimeframe),或直接查询DQL。{ "trainingTimeframe": { "startTime": "now-30d", "endTime": "now-1d" } } - 查询中的注释。以行开头的查询会被提取器正确分类(在
// comment检查前会去除开头的行/块注释)。timeseries
Scripts reference
脚本参考
- scripts/extract-timeseries-dashboard.js — extracts timeseries DQL from a dashboard
- scripts/extract-timeseries-notebook.js — same for notebooks
- scripts/run-analyzer.js — generic Davis analyzer runner
- scripts/extract-timeseries-dashboard.js — 从仪表板提取时间序列DQL
- scripts/extract-timeseries-notebook.js — 从笔记本提取时间序列DQL
- scripts/run-analyzer.js — 通用Davis分析器运行器