dt-obs-analytics

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Analytics — Dashboard & Notebook Query Extraction

分析功能——仪表板与笔记本查询提取

A pipeline of three platform JavaScript scripts under
scripts/
— two extractors feeding a shared analyzer runner:
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
wraps the function return value under
.result
. When you need to inspect the result, read it directly from the output — no
jq
required. Pass the full raw output as
queries
to
run-analyzer.js
and it unwraps automatically.
scripts/
目录下包含三个平台JavaScript脚本组成的流水线——两个提取器将数据传入一个共享的分析器运行器:
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
会将函数返回值包裹在
.result
下。当你需要检查结果时,直接从输出中读取即可——无需使用
jq
。将完整的原始输出作为
queries
传递给
run-analyzer.js
,它会自动进行解包。

Parsing 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 partScript destination
Path segment after
/dashboard/
(before
#
)
id
in extract-timeseries-dashboard.js payload
#from=
value (URL-decode
%3A
:
)
timeframe.startTime
in run-analyzer.js (only needed if running analysis)
#to=
value (URL-decode)
timeframe.endTime
in run-analyzer.js (only needed if running analysis)
vfilter_<name>=<value>
params
variables
map in run-analyzer.js (strip
vfilter_
prefix)
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
$variable
tokens and any embedded
| timeframe
clauses intact. Use the parsed
from
/
to
values only when calling
run-analyzer.js
to set the analysis window. If the user just wants to list the queries, the timeframe is informational only.
Note: when you pass
run-analyzer.js
an absolute
timeframe.startTime
(not a
now...
expression), it strips any embedded
| timeframe ...
stage from the DQL before analysis, so the analyzer honors your requested window rather than the query's baked-in one. For relative (
now...
) windows the embedded
| timeframe
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.
Quick 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部分脚本目标参数
/dashboard/
之后(
#
之前)的路径段
extract-timeseries-dashboard.js
payload中的
id
#from=
的值(URL解码
%3A
:
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):
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
undefined
bash
undefined

All tiles

所有面板

dtctl exec function -f scripts/extract-timeseries-dashboard.js
--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

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

**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"},...]}}
  1. Show the tile names to the user and ask which tile(s) they mean.
  2. Re-run with
    titleFilter
    for only the tile(s) of interest.
This avoids pulling 20–50 DQL queries into context when only 1–2 are relevant.
Payload knobs:
  • id
    (required) — dashboard ID (UUID) or exact name. Preset IDs like
    my.dynatrace.infraops.preview.*
    work.
  • titleFilter
    — case-insensitive substring (
    "CPU usage"
    ) or
    /regex/flags
    (
    "/^kafka/i"
    ).
  • listOnly
    — when
    true
    , returns
    tiles: [{id, title, visualization}]
    without DQL. Use for disambiguation.
  • compact
    — when
    true
    , returns only
    {id, title, dqlQuery}
    per tile (drops description, visualization, isTimeseries). Saves ~40% per-tile tokens. In
    listOnly
    mode, drops visualization too.
  • includeSkipped
    — when
    true
    , returns the full
    skipped[]
    array. Default: only
    skippedCount
    is returned.
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

**当用户指定特定面板、图表或区域时**,将其名称作为`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"},...]}}
  1. 向用户展示面板名称,询问他们需要哪些面板。
  2. 使用
    titleFilter
    重新运行,仅提取感兴趣的面板。
这样可以避免在只需要1–2个查询时,将20–50个DQL查询带入上下文。
Payload参数:
  • id
    (必填)——仪表板ID(UUID)或确切名称。预设IDs如
    my.dynatrace.infraops.preview.*
    可正常使用。
  • titleFilter
    ——不区分大小写的子字符串(
    "CPU usage"
    )或
    /regex/flags
    "/^kafka/i"
    )。
  • listOnly
    ——设为
    true
    时,返回
    tiles: [{id, title, visualization}]
    ,不包含DQL。用于消除歧义。
  • compact
    ——设为
    true
    时,每个面板仅返回
    {id, title, dqlQuery}
    (移除描述、可视化类型、isTimeseries)。可减少约40%的面板令牌数。在
    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
undefined

All cells

所有单元格

dtctl exec function -f scripts/extract-timeseries-notebook.js
--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

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

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

笔记本单元格通常没有标题——如果要定位特定单元格,优先使用响应结构中的`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
undefined

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
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

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

`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 json
Key payload knobs for
run-analyzer.js
:
  • minScore
    — drop results below this threshold (e.g.
    0.5
    ). Auto-detects score field from
    noveltyScore
    ,
    anomalyScore
    ,
    correlationCoefficient
    ,
    correlation
    ,
    coefficient
    . Pass
    scoreField
    to override.
  • scoreField
    — explicit field name to read score from (e.g.
    "noveltyScore"
    ).
The
queries
field accepts any of: a raw array, the extractor envelope (
{queries:[...]}
), or the full dtctl output (
{"result":{"queries":[...]}}
). All three are normalized automatically.
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 ...)`形式可能会达到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 json
run-analyzer.js
的关键Payload参数:
  • minScore
    ——丢弃低于此阈值的结果(例如
    0.5
    )。会自动从
    noveltyScore
    anomalyScore
    correlationCoefficient
    correlation
    coefficient
    中检测分数字段。可传递
    scoreField
    来覆盖。
  • scoreField
    ——读取分数的显式字段名称(例如
    "noveltyScore"
    )。
queries
字段接受以下任意格式:原始数组、提取器响应结构(
{queries:[...]}
)或完整的dtctl输出(
{"result":{"queries":[...]}}
)。这三种格式都会被自动标准化。

Common analyzers

常用分析器

GoalanalyzerNameanalyzerParams
Find anomalous metrics
dt.statistics.anomaly_detection.SeasonalBaselineAnomalyDetectionAnalyzer
{ "trainingTimeframe": { "startTime": "now-8d", "endTime": "now-1d" } }
(optional)
Score how novel each metric is
dt.statistics.NoveltyScoreAnalyzer
{ "detectionMode": "ALL", "minNoveltyScore": 0 }
(optional)
Correlate against a primary metric
dt.statistics.SimplePearsonCorrelationAnalyzer
set
metricQuery
instead (changes call shape)
目标analyzerNameanalyzerParams
查找异常指标
dt.statistics.anomaly_detection.SeasonalBaselineAnomalyDetectionAnalyzer
{ "trainingTimeframe": { "startTime": "now-8d", "endTime": "now-1d" } }
(可选)
计算每个指标的新颖性评分
dt.statistics.NoveltyScoreAnalyzer
{ "detectionMode": "ALL", "minNoveltyScore": 0 }
(可选)
与主指标进行关联
dt.statistics.SimplePearsonCorrelationAnalyzer
改为设置
metricQuery
(会改变调用格式)

Correlation mode

关联模式

Pass
metricQuery
to correlate every query in the set against a single primary DQL string:
bash
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
When chaining from a previous analyzer run (e.g. anomaly detection → correlation), use
metricQueryFrom
instead. The script picks the highest-scored result's
dqlQuery
automatically:
bash
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
takes precedence if both are set.
传递
metricQuery
,将查询集中的每个查询与单个主DQL字符串进行关联:
bash
dtctl exec function -f scripts/run-analyzer.js \
  --payload '{
    "analyzerName": "dt.statistics.SimplePearsonCorrelationAnalyzer",
    "queries": '"$(cat queryset.json)"',
    "metricQuery": "<从提取器输出复制的主面板dqlQuery>",
    "timeframe": { "startTime": "...", "endTime": "..." }
  }' -o json
当从之前的分析器运行结果链式调用时(例如异常检测 → 关联),请改用
metricQueryFrom
。脚本会自动选择得分最高的结果的
dqlQuery
bash
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
metricQueryFrom
metricQuery
优先。

Variable substitution

变量替换

Dashboard queries often contain
$variable
tokens (from URL
vfilter_*
params). Pass them via
variables
to substitute before execution:
bash
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
Build
variables
from
vfilter_*
URL params by stripping the
vfilter_
prefix. Trailing
*
wildcards are stripped automatically. Unresolved tokens are cleaned up from DQL filter clauses rather than left to error.
仪表板查询通常包含
$variable
标记(来自URL的
vfilter_*
参数)。通过
variables
传递这些变量,在执行前进行替换:
bash
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
通过去除
vfilter_
前缀,从URL的
vfilter_*
参数构建
variables
。末尾的
*
通配符会被自动去除。未解析的标记会从DQL过滤子句中清除,而非保留导致错误。

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
output
field is the raw analyzer result. Interpret it based on the analyzer:
  • Anomaly detection: look for
    anomalyScore
    ,
    anomalies[]
    , or
    raisedAlerts[]
    in each output entry. Score ≥ 0.7 → abnormal, ≥ 0.4 → borderline.
  • Novelty: look for
    noveltyScore
    (or the closest score-like numeric field). Score ≥ 0.7 → novel.
  • Correlation: look for
    correlationCoefficient
    . Sort by
    |correlationCoefficient|
    descending; drop entries where
    |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[]
    raisedAlerts[]
    。评分≥0.7 → 异常,≥0.4 → 临界。
  • 新颖性评分:查找
    noveltyScore
    (或最接近的类分数数字字段)。评分≥0.7 → 新颖。
  • 关联分析:查找
    correlationCoefficient
    。按
    |correlationCoefficient|
    降序排序;丢弃
    |correlationCoefficient| < 0.5
    的条目。

End-to-end: "what's abnormal on this dashboard?"

端到端流程:“这个仪表板有什么异常?”

bash
undefined
bash
undefined

1. 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
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

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
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

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
undefined
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
undefined

Verifying a single extracted query

验证单个提取的查询

Read the
dqlQuery
field from the extractor output and pass it directly:
bash
dtctl query --query "<dqlQuery copied from extractor output>" -o json | head -40
从提取器输出中读取
dqlQuery
字段并直接传递:
bash
dtctl query --query "<从提取器输出复制的dqlQuery>" -o json | head -40

Gotchas

注意事项

  • Never read raw dashboard JSON yourself.
    dtctl get dashboard <id> -o json
    is typically 50–200 KB. The extractor reads it on the platform and returns a compact envelope (~5–15 KB).
  • 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
    titleFilter
    . If it's ambiguous, use
    listOnly: true
    first to ask which tile — then extract only that one.
  • Variables are required for filtered dashboards. Queries with unsubstituted
    $variable
    tokens silently drop entity filters (e.g.
    in(field, $undefined)
    evaluates to
    true
    ). Always pass
    variables
    when the URL has
    vfilter_*
    params.
  • Schema drift. If a tile lands in
    skipped
    with reason
    no DQL query found
    , the dashboard schema has a query location the extractor doesn't know about — add it to the
    pickQuery
    candidate list in the script.
  • Analyzer availability. Not all Davis analyzers are available on every tenant. If a call comes back with
    Could not find an analyzer with name '...'
    or
    is not a function
    , list what's actually registered:
    dtctl get analyzers -o json
    .
  • Statistical fallback removed.
    run-analyzer.js
    only calls Davis analyzers. For historical anomaly detection, pass a long
    trainingTimeframe
    via
    analyzerParams
    (e.g.
    { "trainingTimeframe": { "startTime": "now-30d", "endTime": "now-1d" } }
    ), or query the DQL directly.
  • Comments in queries. Queries starting with
    // comment
    lines are classified correctly by the extractor (leading line/block comments are stripped before the
    timeseries
    check).
  • 切勿自行读取原始仪表板JSON
    dtctl get dashboard <id> -o json
    通常为50–200 KB。提取器会在平台上读取它并返回紧凑的响应结构(约5–15 KB)。
  • 切勿在仅需要一个面板时提取所有面板。包含50个面板的仪表板会返回50个DQL查询到上下文中。如果用户指定了面板名称,请使用
    titleFilter
    。如果存在歧义,请先使用
    listOnly: true
    询问用户需要哪个面板——然后仅提取该面板。
  • 过滤后的仪表板需要变量。带有未替换
    $variable
    标记的查询会静默删除实体过滤器(例如
    in(field, $undefined)
    会被评估为
    true
    )。当URL包含
    vfilter_*
    参数时,务必传递
    variables
  • Schema漂移。如果某个面板因
    no DQL query found
    原因被列入
    skipped
    ,说明仪表板schema存在提取器未知的查询位置——请将其添加到脚本中的
    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 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分析器运行器