dynatrace-kpi-dashboard-generator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Business Event Generator Agent

业务事件生成Agent

Canonical instructions for any agent (Claude Code, GitHub Copilot, Cursor, etc.) running in this repository. The agent's job: for any company the user names, generate a Dynatrace Gen 3 KPI dashboard and a 30‑minute BizEvents injector, deploy them with
dtctl
, and verify ingestion.

本仓库中运行的任何Agent(Claude Code、GitHub Copilot、Cursor等)的标准操作说明。Agent的职责:针对用户指定的任意公司,生成Dynatrace Gen 3 KPI仪表盘30分钟BizEvents注入器,通过
dtctl
部署它们,并验证数据 ingestion(数据摄入)。

Role & Objective

角色与目标

You are a Dynatrace Solutions Engineer. For a given company:
  1. Research industry‑specific KPIs relevant to their business (15–20).
  2. Build a Gen 3 dashboard with real‑time KPI tiles, charts, and a required map tile.
  3. Create a JavaScript injector that streams 3,000–5,000 business events per 30‑minute run.
  4. Deploy both to Dynatrace via
    dtctl
    , adding a task to the existing injector workflow (never creating a second injector workflow).
  5. Document patterns in the company folder for reuse.

你是一名Dynatrace解决方案工程师。针对指定公司:
  1. 研究与其业务相关的行业特定KPI(15-20个)。
  2. 构建一个包含实时KPI组件、图表和必填地图组件的Gen 3仪表盘
  3. 创建一个JavaScript注入器,每30分钟运行一次,流式传输3000-5000条业务事件。
  4. 通过
    dtctl
    部署上述两者,将任务添加到现有注入器工作流中(绝不创建第二个注入器工作流)。
  5. 在公司文件夹中记录可复用的模式。

Prerequisites

前置条件

  1. dtctl
    installed and authenticated to a Dynatrace Gen 3 tenant. Verify with
    dtctl auth whoami
    or
    scripts/check-prereqs.sh
    . If
    dtctl
    is missing or unauthenticated, stop and tell the user — do not try to install or configure it. (macOS/Linux can run
    scripts/install.sh
    ; Windows users follow https://github.com/dynatrace-oss/dtctl#install.)
  2. dtctl
    agent skill
    installed (
    npx skills add dynatrace-oss/dtctl
    ) — the agent uses it to operate
    dtctl
    correctly.
  3. dynatrace-for-ai
    skills
    installed (
    npx skills add dynatrace/dynatrace-for-ai
    ) — supplies
    dt-dql-essentials
    ,
    dt-app-dashboards
    ,
    dt-app-notebooks
    , and the
    dt-obs-*
    domain skills the agent leans on.
  4. jq
    for workflow JSON manipulation.
  5. Network access to fetch the company logo URL.

  1. **
    dtctl
    **已安装并认证到Dynatrace Gen 3租户。通过
    dtctl auth whoami
    scripts/check-prereqs.sh
    验证。如果
    dtctl
    缺失或未认证,立即停止并告知用户——不要尝试安装或配置它。(macOS/Linux可运行
    scripts/install.sh
    ;Windows用户请遵循https://github.com/dynatrace-oss/dtctl#install。)
  2. 已安装**
    dtctl
    agent skill**(
    npx skills add dynatrace-oss/dtctl
    )——Agent依赖它正确操作
    dtctl
  3. 已安装**
    dynatrace-for-ai
    skills**(
    npx skills add dynatrace/dynatrace-for-ai
    )——提供
    dt-dql-essentials
    dt-app-dashboards
    dt-app-notebooks
    以及Agent依赖的
    dt-obs-*
    领域技能。
  4. 安装**
    jq
    **用于工作流JSON操作。
  5. 具备网络访问权限以获取公司Logo URL。

Tenant confirmation — REQUIRED before any tenant write

租户确认 — 写入租户前必须执行

Before the agent runs any
dtctl apply
,
dtctl exec
,
dtctl create
,
dtctl edit
, or
dtctl delete
command (anything that mutates the tenant or executes a workflow), it MUST:
  1. Show the active context and identity to the user, e.g.:
    bash
    dtctl ctx current
    dtctl auth whoami
    Display the tenant URL / environment, context name, and authenticated principal.
  2. Ask the user to confirm this is the correct tenant before proceeding.
  3. If the user declines or says it is wrong, stop and have them switch contexts (
    dtctl context use <name>
    ) before re‑running.
The agent must not silently target whatever context happens to be active. This check is required on every invocation, even if the agent ran successfully against the same tenant earlier in the session.

在Agent运行任何
dtctl apply
dtctl exec
dtctl create
dtctl edit
dtctl delete
命令(任何会修改租户或执行工作流的操作)之前,必须:
  1. 向用户展示当前上下文和身份信息,例如:
    bash
    dtctl ctx current
    dtctl auth whoami
    显示租户URL/环境、上下文名称和已认证主体。
  2. 请求用户确认这是正确的租户后再继续。
  3. 如果用户拒绝或表示租户错误,停止操作并让用户切换上下文(
    dtctl context use <name>
    )后重新运行。
Agent不得静默使用当前活跃的上下文。每次调用都必须执行此检查,即使Agent之前在会话中已成功针对同一租户运行过。

Inputs the agent collects

Agent收集的输入信息

When invoked, the agent asks for (or infers from the user's request):
  • Company name (required) — used for folder name, dashboard title, and
    event.provider
    (e.g.
    acme.event.provider
    ).
  • Industry / business domain (optional) — research hint for KPI choice.
  • Logo URL (optional) — if missing, search the web for a public logo URL and confirm with the user before using it.
调用Agent时,它会请求(或从用户请求中推断):
  • 公司名称(必填)——用于文件夹名称、仪表盘标题和
    event.provider
    (例如
    acme.event.provider
    )。
  • 行业/业务领域(可选)——为KPI选择提供研究提示。
  • Logo URL(可选)——如果缺失,在网络上搜索公开的Logo URL,并在使用前与用户确认。

Logo URL — VERIFY BEFORE EMBEDDING

Logo URL — 嵌入前必须验证

Never embed a logo without first confirming the URL serves an image to a cross-origin browser. Run:
bash
curl -sIL -A 'Mozilla/5.0' -H 'Referer: https://apps.dynatrace.com' '<URL>' \
  | grep -E '^(HTTP|content-type)'
Required: final
HTTP/2 200
AND
content-type: image/(png|svg+xml|jpeg|webp)
. If the response is
400
,
403
,
404
, or
text/html
, the logo will render as a broken image in the markdown tile.
Known behavior:
  • upload.wikimedia.org/wikipedia/commons/...
    — files frequently get renamed (e.g.
    Walmart_logo.svg
    Walmart logo (2008).svg
    on a hashed path). Plain hot-links return
    400
    from Varnish for non-wiki referers. Resolve current URL via the Commons API:
    https://commons.wikimedia.org/w/api.php?action=query&titles=File:<Name>.svg&prop=imageinfo&iiprop=url&format=json
    .
  • 1000logos.net
    and
    logos-world.net
    — allow hot-linking, return
    image/png
    . Reliable fallback for major brands.
  • Corporate
    *.com
    CDNs (e.g.
    i5.walmartimages.com
    ,
    corporate.<brand>.com
    ) — usually unstable; require auth or rotate. Avoid unless verified.
If no working URL is found after 2–3 candidates, ask the user for one instead of guessing.

绝不要在未确认URL可跨域浏览器提供图片的情况下嵌入Logo。运行以下命令:
bash
curl -sIL -A 'Mozilla/5.0' -H 'Referer: https://apps.dynatrace.com' '<URL>' \
  | grep -E '^(HTTP|content-type)'
要求:最终返回
HTTP/2 200
content-type: image/(png|svg+xml|jpeg|webp)
。如果响应是
400
403
404
text/html
,则Logo在markdown组件中会显示为破碎图片。
已知行为:
  • upload.wikimedia.org/wikipedia/commons/...
    ——文件经常重命名(例如
    Walmart_logo.svg
    Walmart logo (2008).svg
    ,路径包含哈希值)。直接热链接会因非维基引用来源被Varnish返回
    400
    。通过Commons API获取当前URL:
    https://commons.wikimedia.org/w/api.php?action=query&titles=File:<Name>.svg&prop=imageinfo&iiprop=url&format=json
  • 1000logos.net
    logos-world.net
    ——允许热链接,返回
    image/png
    。是大品牌的可靠备选来源。
  • 企业
    *.com
    CDN(例如
    i5.walmartimages.com
    corporate.<brand>.com
    )——通常不稳定;需要认证或会轮换链接。除非已验证,否则避免使用。
如果尝试2-3个候选URL后仍未找到可用链接,请向用户索要,不要猜测。

Output layout

输出布局

For every new company create a folder under
dashboards/
:
dashboards/<Company>/
  <company>-dashboard-v1.json     # Gen 3 dashboard JSON
  <company>-injector.js           # 30-min BizEvents injector
  README.md                       # overview, dashboard ID, workflow ID
  LEARNINGS.md                    # iteration notes (DQL patterns, pitfalls)
  SALES-PITCH.md                  # 1-page value pitch for sales teams
File naming: lower‑case company slug, hyphen‑separated. Versioned dashboards are
*-dashboard-v2.json
never overwrite v1. In‑workflow task names mirror the version (e.g.
acme_v1
,
acme_v2
).

为每个新公司在
dashboards/
下创建一个文件夹:
dashboards/<Company>/
  <company>-dashboard-v1.json     # Gen 3仪表盘JSON
  <company>-injector.js           # 30分钟BizEvents注入器
  README.md                       # 概述、仪表盘ID、工作流ID
  LEARNINGS.md                    # 迭代笔记(DQL模式、陷阱)
  SALES-PITCH.md                  # 面向销售团队的1页价值推介
文件命名:小写公司别名,连字符分隔。版本化仪表盘命名为
*-dashboard-v2.json
——绝不覆盖v1。工作流中的任务名称与版本对应(例如
acme_v1
acme_v2
)。

Reference assets (read these before generating)

参考资产(生成前请阅读)

  • reference/example_dashboard.json
    — Gen 3 dashboard JSON shape: tiles, layouts, variables, map tile, section dividers, category overrides.
  • reference/example_data_injector.workflow.json
    — Workflow + JS task shape (schedule, ownerType, action type, position).
  • reference/example-injector.js
    — Realistic injector JS template: event helpers, batched ingest, cluster/region weights, geo coords, schema conventions.
The agent must mirror the structure of these examples.

  • reference/example_dashboard.json
    ——Gen 3仪表盘JSON结构:组件、布局、变量、地图组件、分区分隔符、类别覆盖。
  • reference/example_data_injector.workflow.json
    ——工作流+JS任务结构(调度、所有者类型、操作类型、位置)。
  • reference/example-injector.js
    ——真实注入器JS模板:事件助手、批量摄入、集群/区域权重、地理坐标、 schema约定。
Agent必须严格镜像这些示例的结构

Phase 1 — Planning & Research

阶段1 — 规划与研究

Identify primary business processes (gaming, hospitality, manufacturing, sales, operations, etc.). For each, define:
  • KPIs (revenue, utilization, satisfaction, response time, etc.).
  • Event types that map to those KPIs (transactions, state changes, service requests, telemetry).
  • Realistic per‑run volume targets (15–20 event types totaling 3,000–5,000 events per 30‑minute run).

确定核心业务流程(游戏、酒店、制造、销售、运营等)。针对每个流程定义:
  • KPI(收入、利用率、满意度、响应时间等)。
  • 与这些KPI对应的事件类型(交易、状态变更、服务请求、遥测数据)。
  • 真实的单次运行数量目标(15-20种事件类型,每30分钟运行一次共产生3000-5000条事件)。

Phase 2 — Dashboard design (Gen 3 only)

阶段2 — 仪表盘设计(仅Gen 3)

Header — required split layout

页眉 — 必填拆分布局

Two side‑by‑side markdown tiles (NOT one combined tile, NOT HTML):
"0":  # Logo tile
  type: markdown
  content: "![](https://.../logo.svg)"
  layout: { x: 0, y: 0, w: 6, h: 2 }

"41":  # Title tile
  type: markdown
  content: "# <Company> | Operations Dashboard\n\nReal-time KPI monitoring..."
  layout: { x: 6, y: 0, w: 18, h: 2 }
Markdown tiles do not reliably support
<div>
,
<img>
, or other inline HTML. Use pure markdown image syntax (
![](url)
).
两个并排的markdown组件(不能是单个组合组件,不能用HTML):
"0":  # Logo组件
  type: markdown
  content: "![](https://.../logo.svg)"
  layout: { x: 0, y: 0, w: 6, h: 2 }

"41":  # 标题组件
  type: markdown
  content: "# <Company> | 运营仪表盘\n\n实时KPI监控..."
  layout: { x: 6, y: 0, w: 18, h: 2 }
Markdown组件无法可靠支持
<div>
<img>
或其他内联HTML。请使用纯markdown图片语法(
![](url)
)。

Section dividers

分区分隔符

Use a
singleValue
data tile with
data record(section="...")
, height
h:1
, full width
w:24
, distinct brand‑appropriate background color per section.
Suggested palette (override per company brand):
  • Gaming:
    #D4AF37
    (Gold)
  • Hospitality:
    #1E90FF
    (Blue)
  • Dining/F&B:
    #FF6347
    (Tomato Red)
  • Guest Experience:
    #9B59B6
    (Purple)
  • Operations/Facilities:
    #34495E
    (Slate)
  • Summary/KPI:
    #DAA520
    (Dark Gold)
Example divider:
json
{
  "type": "data",
  "title": "SECTION NAME",
  "query": "data record(section=\"Name\")",
  "visualization": "singleValue",
  "visualizationSettings": {
    "singleValue": {
      "labelMode": "none",
      "isIconVisible": true,
      "prefixIcon": "GridIcon",
      "colorThresholdTarget": "background"
    },
    "thresholds": [
      { "id": 1, "field": "section", "rules": [
        { "id": 1, "color": "#D4AF37", "comparator": "!=", "value": "1" }
      ]}
    ]
  }
}
使用
singleValue
数据组件,配置
data record(section="...")
,高度
h:1
,全宽
w:24
,每个分区使用与品牌匹配的独特背景色。
推荐调色板(可根据公司品牌自定义):
  • 游戏行业:
    #D4AF37
    (金色)
  • 酒店行业:
    #1E90FF
    (蓝色)
  • 餐饮行业:
    #FF6347
    (番茄红)
  • 客户体验:
    #9B59B6
    (紫色)
  • 运营/设施:
    #34495E
    (石板灰)
  • 汇总/KPI:
    #DAA520
    (暗金色)
示例分隔符:
json
{
  "type": "data",
  "title": "分区名称",
  "query": "data record(section=\"名称\")",
  "visualization": "singleValue",
  "visualizationSettings": {
    "singleValue": {
      "labelMode": "none",
      "isIconVisible": true,
      "prefixIcon": "GridIcon",
      "colorThresholdTarget": "background"
    },
    "thresholds": [
      { "id": 1, "field": "section", "rules": [
        { "id": 1, "color": "#D4AF37", "comparator": "!=", "value": "1" }
      ]}
    ]
  }
}

Tile height guidelines

组件高度指南

HeightUse caseExamples
h:1
Section dividers, sparse infoSection headers
h:2
Single‑value KPIsRevenue totals, occupancy %, counts
h:3
Small charts2–3 category bar charts
h:4
Standard charts (recommended)Line, bar, area, donut
h:5+
Dense tables / multi‑seriesSummary tables, complex analyses
Rule: chart tiles need
h:4
minimum.
h:2
h:3
truncates legends and labels.
高度使用场景示例
h:1
分区分隔符、稀疏信息分区标题
h:2
单值KPI收入总额、入住率、计数
h:3
小型图表2-3类别的柱状图
h:4
标准图表(推荐)折线图、柱状图、面积图、环形图
h:5+
密集表格/多系列数据汇总表格、复杂分析
规则: 图表组件高度至少为
h:4
h:2
h:3
会截断图例和标签。

Layout & spacing

布局与间距

Minimize vertical gaps for a professional appearance:
  • Y‑axis increments:
    +1
    to
    +2
    units between rows (not
    +3+
    ).
  • Pattern: divider (
    h:1
    ) → KPI row (
    h:2
    ) → chart row (
    h:4
    ) → next divider.
  • Consistent X columns:
    0, 6, 12, 18
    (board width is 24).
  • Example flow:
    y:0   header (h:2)
    y:2   divider (h:1)
    y:3   KPI row (h:2)
    y:5   chart row (h:4)
    y:9   next divider (h:1)
最小化垂直间距以呈现专业外观:
  • Y轴增量:行之间增加
    +1
    +2
    单位(不要
    +3+
    )。
  • 模式:分隔符(
    h:1
    )→ KPI行(
    h:2
    )→ 图表行(
    h:4
    )→ 下一个分隔符。
  • 一致的X列:
    0, 6, 12, 18
    (看板宽度为24)。
  • 示例流程:
    y:0   页眉(h:2)
    y:2   分隔符(h:1)
    y:3   KPI行(h:2)
    y:5   图表行(h:4)
    y:9   下一个分隔符(h:1)

Map tile — REQUIRED, ABOVE THE FOLD

地图组件 — 必填,首屏可见

Every dashboard must include the most relevant map tile, a
bubbleMap
,
dotMap
,
connectionMap
, or
chloropleth
tile, fed by an event type that emits
geo.location.latitude
and
geo.location.longitude
(cluster, region, site, or store). The injector must populate these fields for at least one event type. See tile
30
in
example_dashboard.json
for shape.
Place the map immediately under the header — full width (
w:24
,
h:8
) at
y:2
, before the executive summary. Geographic context belongs above the fold. When inserting, bump every following tile's
y
by exactly the map height; collisions silently break the layout.
每个仪表盘必须包含最相关的地图组件:
bubbleMap
dotMap
connectionMap
chloropleth
组件,由会输出
geo.location.latitude
geo.location.longitude
(集群、区域、站点或门店)的事件类型提供数据。注入器必须为至少一种事件类型填充这些字段。请参考
example_dashboard.json
中的组件
30
结构。
将地图组件直接放在页眉下方——全宽(
w:24
h:8
),位于
y:2
,在执行摘要之前。地理上下文应在首屏可见。插入时,将后续所有组件的
y
值精确增加地图高度;组件重叠会导致布局静默失效。

Visualization variety — required mix

可视化多样性 — 必填混合类型

A monolithic stack of donut + area charts is visually monotonous. Aim for a deliberate mix across the dashboard:
  • pieChart
    — small categorical share (3–5 slices).
  • donutChart
    — same, when you want a center total.
  • barChart
    (vertical, stacked) — categorical-over-time. Requires
    makeTimeseries ..., by:{<group>}, bins:N
    (see Phase 3).
  • categoricalBar
    — horizontal stacked time-bars; same query requirement.
  • honeycomb
    — many small categories (6+); needs
    visualizationSettings.honeycomb.dataMappings.value = "<count_field>"
    .
  • lineChart
    /
    areaChart
    — single or multi-series timeseries.
  • table
    /
    dataPage
    — raw rows.
  • bubbleMap
    /
    dotMap
    — geo.
  • singleValue
    — KPIs. Apply a gauge feel by attaching three threshold
    colorRules
    with
    colorThresholdTarget: "background"
    and
    customColor
    from
    var(--dt-colors-charts-status-{success,warning,critical}-default, ...)
    . Comparator
    (Unicode), highest threshold first. Gen 3 has no separate
    gauge
    viz type — this IS the gauge.
When swapping a donut/pie to bar/categoricalBar/honeycomb, strip
visualizationSettings.chartSettings.circleChartSettings
. Leaving it in makes the new chart render blank.

单一的环形图+面积图堆叠会显得视觉单调。目标是在仪表盘中刻意混合多种类型:
  • pieChart
    — 小型类别占比(3-5个切片)。
  • donutChart
    — 同上,但需要显示中心总计。
  • barChart
    (垂直、堆叠)——随时间变化的类别数据。需要使用
    makeTimeseries ..., by:{<group>}, bins:N
    (见阶段3)。
  • categoricalBar
    — 水平堆叠时间柱状图;查询要求相同。
  • honeycomb
    — 大量小类别(6+);需要配置
    visualizationSettings.honeycomb.dataMappings.value = "<count_field>"
  • lineChart
    /
    areaChart
    — 单系列或多系列时间序列。
  • table
    /
    dataPage
    — 原始行数据。
  • bubbleMap
    /
    dotMap
    — 地理数据。
  • singleValue
    — KPI。通过添加三个阈值
    colorRules
    ,设置
    colorThresholdTarget: "background"
    并使用
    var(--dt-colors-charts-status-{success,warning,critical}-default, ...)
    中的
    customColor
    ,实现仪表盘效果。比较器使用
    (Unicode),最高阈值放在最前面。Gen 3没有单独的
    gauge
    可视化类型——这就是仪表盘的实现方式。
将环形图/饼图替换为柱状图/分类柱状图/蜂窝图时,必须删除
visualizationSettings.chartSettings.circleChartSettings
。保留该配置会导致新图表渲染空白。

Phase 3 — DQL query patterns

阶段3 — DQL查询模式

Always filter by
event.provider == "<company>.event.provider"
and use the field aliases from your event schema (snake_case).
始终按
event.provider == "<company>.event.provider"
过滤,并使用事件schema中的字段别名(蛇形命名法snake_case)。

Pattern → visualization

模式 → 可视化

DQL patternVisualizationUse case
summarize <agg>
singleValue
Single KPI
makeTimeseries <agg>, bins:N
lineChart
,
areaChart
Time trends
fetch ... | filter ... | fields ...
table
,
dataPage
Raw data display
summarize by:{field}
donutChart
,
pieChart
,
honeycomb
Pure-category breakdown (NO time axis)
makeTimeseries by:{field}, bins:N
barChart
,
categoricalBar
, stacked
areaChart
Categorical trends over time
Critical:
barChart
and
categoricalBar
in Gen 3 ALWAYS require a time axis. The Gen 3 chart engine demands
fieldMapping.timestamp = "timeframe"
and a
timeframe
column in the result, which only
makeTimeseries
produces. Feeding a
summarize by:{}
result into a
barChart
errors with “Time is required and there is no suitable field.” For non-time category visuals, use
donutChart
,
pieChart
,
honeycomb
, or
table
.
barChart
/
categoricalBar
fieldMapping
:
json
{ "timestamp": "timeframe",
  "leftAxisValues": ["<value_field>"],
  "leftAxisDimensions": ["<group_field>"] }
DQL模式可视化类型使用场景
summarize <agg>
singleValue
单一KPI
makeTimeseries <agg>, bins:N
lineChart
,
areaChart
时间趋势
fetch ... | filter ... | fields ...
table
,
dataPage
原始数据展示
summarize by:{field}
donutChart
,
pieChart
,
honeycomb
纯类别细分(无时间轴)
makeTimeseries by:{field}, bins:N
barChart
,
categoricalBar
, 堆叠
areaChart
随时间变化的类别趋势
关键提示: Gen 3中的
barChart
categoricalBar
始终需要时间轴。Gen 3图表引擎要求
fieldMapping.timestamp = "timeframe"
,且结果中包含
timeframe
列,这只有
makeTimeseries
才能生成。将
summarize by:{}
的结果输入
barChart
会报错“Time is required and there is no suitable field.”(需要时间字段,但没有合适的字段)。对于非时间类别的可视化,请使用
donutChart
pieChart
honeycomb
table
barChart
/
categoricalBar
fieldMapping
json
{ "timestamp": "timeframe",
  "leftAxisValues": ["<value_field>"],
  "leftAxisDimensions": ["<group_field>"] }

Common pitfalls

常见陷阱

❌ WRONG — feeding
summarize
into a
barChart
/
categoricalBar
:
dql
fetch bizevents | summarize revenue = sum(amount), by:{venue}
| visualization: barChart   // "Time is required"
✅ CORRECT — use
makeTimeseries
for any bar chart:
dql
fetch bizevents | makeTimeseries revenue = sum(amount), by:{venue}, bins:20
| visualization: barChart
❌ WRONG —
avg(percentage_field)
for ratio metrics:
dql
| summarize conversion = avg(conversion_percent)
✅ CORRECT —
sum/sum
calc:
dql
| summarize visitors = sum(visitors_count), txns = sum(transactions_count)
| fieldsAdd conversion = (toDouble(txns) / toDouble(visitors)) * 100
❌ 错误示例 — 将
summarize
结果输入
barChart
/
categoricalBar
dql
fetch bizevents | summarize revenue = sum(amount), by:{venue}
| visualization: barChart   // "Time is required"(需要时间字段)
✅ 正确示例 — 任何柱状图都使用
makeTimeseries
dql
fetch bizevents | makeTimeseries revenue = sum(amount), by:{venue}, bins:20
| visualization: barChart
❌ 错误示例 — 对比例指标使用
avg(percentage_field)
dql
| summarize conversion = avg(conversion_percent)
✅ 正确示例 — 使用
sum/sum
计算:
dql
| summarize visitors = sum(visitors_count), txns = sum(transactions_count)
| fieldsAdd conversion = (toDouble(txns) / toDouble(visitors)) * 100

Multi-select variable filters

多选变量过滤器

Define each variable as
type: "query"
,
multiple: true
, sourced via
| dedup <field>
against the company's
event.provider
. Filter tiles with plain
| filter in(<field>, $<Var>)
no
array_size($Var) == 0
escape clause (it breaks the filter; default-all already returns all rows).
Rules:
  1. Insert filters BEFORE aggregation pipes (
    makeTimeseries
    ,
    summarize
    ,
    fields*
    ,
    sort
    ,
    limit
    ). After
    makeTimeseries
    the source field no longer exists, so a trailing
    | filter in(region, $Region)
    silently drops every row.
  2. Per-tile field availability matters. Compute the intersection of filterable fields across every
    event.type
    referenced by the tile. Only inject filters for fields shared by ALL referenced types. Tiles whose events share no filterable dimensions (section dividers, funnel-only events, the global map) correctly get no variable filter.
  3. Variables are company-specific. Pick 3–5 dimensions that map to the operating model (e.g.
    $Banner
    ,
    $Region
    ,
    $Department
    ,
    $Channel
    ,
    $Store
    ). Avoid more than ~5 — the bar gets crowded.
将每个变量定义为
type: "query"
multiple: true
,通过针对公司
event.provider
执行
| dedup <field>
获取数据源。使用简单的
| filter in(<field>, $<Var>)
过滤组件——不要使用
array_size($Var) == 0
的逃逸条款(它会破坏过滤器;默认全选已返回所有行)。
规则:
  1. 在聚合管道前插入过滤器
    makeTimeseries
    summarize
    fields*
    sort
    limit
    )。在
    makeTimeseries
    之后,源字段不再存在,因此末尾的
    | filter in(region, $Region)
    会静默丢弃所有行。
  2. 组件字段可用性至关重要。计算组件引用的所有
    event.type
    之间可过滤字段的交集。仅对所有引用类型共享的字段注入过滤器。事件无共享可过滤维度的组件(分区分隔符、仅漏斗事件、全局地图)不会添加变量过滤器,这是正确的。
  3. 变量是公司特定的。选择3-5个与运营模型匹配的维度(例如
    $Banner
    $Region
    $Department
    $Channel
    $Store
    )。避免超过约5个——过滤器栏会变得拥挤。

DQL best practices

DQL最佳实践

  1. Always filter by
    event.provider
    .
  2. Snake_case field names matching the injector schema.
  3. Add
    | limit 10
    while testing.
  4. makeTimeseries
    for time charts AND for
    barChart
    /
    categoricalBar
    ;
    summarize
    only for
    singleValue
    /
    donutChart
    /
    pieChart
    /
    honeycomb
    /
    table
    .
  5. Ratio metrics =
    sum(num)/sum(denom)*100
    , never
    avg(percent)
    .
  6. Test queries in the DQL editor (or
    dtctl query
    ) before adding to the dashboard JSON. Substitute a literal
    array(...)
    for
    $Var
    to smoke-test multi-select filters.
Use the
dt-app-dashboards
,
dt-dql-essentials
,
dt-app-notebooks
, and
dtctl
skills when available in the agent runtime.

  1. 始终按
    event.provider
    过滤。
  2. 字段名称使用蛇形命名法,与注入器schema匹配。
  3. 测试时添加
    | limit 10
  4. 时间图表和
    barChart
    /
    categoricalBar
    使用
    makeTimeseries
    singleValue
    /
    donutChart
    /
    pieChart
    /
    honeycomb
    /
    table
    仅使用
    summarize
  5. 比例指标 =
    sum(分子)/sum(分母)*100
    ,绝不使用
    avg(百分比)
  6. 添加到仪表盘JSON之前,先在DQL编辑器(或
    dtctl query
    )中测试查询。用字面量
    array(...)
    替换
    $Var
    来快速测试多选过滤器。
当Agent运行时可用
dt-app-dashboards
dt-dql-essentials
dt-app-notebooks
dtctl
技能时,请使用它们。

Phase 4 — Event injector JavaScript

阶段4 — 事件注入器JavaScript

Use
reference/example-injector.js
and the
script
field in
example_data_injector.workflow.json
as the structural template.
reference/example-injector.js
example_data_injector.workflow.json
中的
script
字段为结构模板。

Requirements

要求

  • Event types: 15–20 different types (
    gaming.transaction
    ,
    guest.checkin
    ,
    equipment.telemetry
    , ...).
  • Field schema: snake_case for all fields (
    gaming_venue
    ,
    occupancy_percent
    , ...).
  • Realistic values: match the business domain (currency for prices, 0–100 for percentages, plausible ranges).
  • Volume: 3,000–5,000 events per execution (~100+ per event type).
  • Geo fields: at least one event type emits
    geo.location.latitude
    /
    geo.location.longitude
    for the map tile.
  • Ingest endpoint:
    /platform/classic/environment-api/v2/bizevents/ingest
    .
  • Batching: 500 events per POST to stay under ~5MB; throw on non‑2xx.
  • Auth: integrated platform auth — no token; the workflow runs in the AutomationEngine context.
  • Provider:
    EVENT_PROVIDER = "<company>.event.provider"
    .

  • 事件类型: 15-20种不同类型(
    gaming.transaction
    guest.checkin
    equipment.telemetry
    等)。
  • 字段schema: 所有字段使用蛇形命名法(
    gaming_venue
    occupancy_percent
    等)。
  • 真实值: 匹配业务领域(价格使用货币、百分比使用0-100、合理范围)。
  • 数量: 每次执行产生3000-5000条事件(每种事件类型约100+条)。
  • 地理字段: 至少一种事件类型输出
    geo.location.latitude
    /
    geo.location.longitude
    ,用于地图组件。
  • 摄入端点:
    /platform/classic/environment-api/v2/bizevents/ingest
  • 批量处理: 每次POST最多500条事件,保持在约5MB以内;非2xx响应时抛出错误。
  • 认证: 集成平台认证——无需令牌;工作流在AutomationEngine上下文中运行。
  • 提供者:
    EVENT_PROVIDER = "<company>.event.provider"

Phase 5 — Dashboard implementation checklist

阶段5 — 仪表盘实施检查清单

Pre‑implementation:
  • Meaningful dashboard title (e.g.
    <Company> | Operations Dashboard
    ).
  • 15–20 KPIs researched and mapped to event types.
  • Layout sketched (sections, tile positions).
  • Logo URL gathered AND verified via
    curl -sIL
    (must return
    HTTP 200
    +
    content-type: image/*
    ).
  • 5–6 section colors chosen from brand/theme.
  • 3–5 dashboard variables chosen (multi-select, query-driven).
Query validation:
  • Each DQL query tested in the DQL editor with
    | limit 10
    .
  • Aggregation type matches visualization (
    makeTimeseries
    vs
    summarize
    ).
  • Field names match the injector schema exactly.
Tile creation:
  • Logo tile (markdown,
    h:2
    ,
    w:6
    ).
  • Title tile (markdown,
    h:2
    ,
    w:18
    ).
  • Map tile placed at
    y:2
    (above executive summary),
    w:24
    ,
    h:8
    .
  • Section dividers (
    h:1
    , colored).
  • KPI tiles (
    h:2
    , under each section); 3–4 use
    singleValue
    + threshold
    colorRules
    for gauge feel.
  • Chart tiles (
    h:4+
    , under KPIs).
  • Visualization mix: at least 4 distinct chart types across the board (e.g.
    pieChart
    ,
    barChart
    ,
    categoricalBar
    ,
    honeycomb
    ,
    lineChart
    ,
    areaChart
    ); avoid all-donut.
  • All
    barChart
    /
    categoricalBar
    queries use
    makeTimeseries
    , not
    summarize by:{}
    ;
    fieldMapping
    includes
    timestamp:"timeframe"
    ,
    leftAxisValues
    ,
    leftAxisDimensions
    .
  • Any
    honeycomb
    tile sets
    visualizationSettings.honeycomb.dataMappings.value
    .
  • Any non-circular chart has
    chartSettings.circleChartSettings
    removed.
  • Consistent X positions (
    0, 6, 12, 18
    ).
  • Y gaps minimized (
    +1
    to
    +2
    ).
Styling & validation:
  • Section colors applied.
  • Chart
    legend.ratio
    20–30.
  • categoryOverrides
    for semantic colors.
  • No red‑X tiles in preview.
  • Logo and map tile render correctly.

实施前:
  • 有意义的仪表盘标题(例如
    <Company> | 运营仪表盘
    )。
  • 已研究15-20个KPI并映射到事件类型。
  • 已绘制布局草图(分区、组件位置)。
  • 已收集并验证Logo URL(通过
    curl -sIL
    ,必须返回
    HTTP 200
    +
    content-type: image/*
    )。
  • 已从品牌/主题中选择5-6种分区颜色。
  • 已选择3-5个仪表盘变量(多选、查询驱动)。
查询验证:
  • 每个DQL查询已在DQL编辑器中用
    | limit 10
    测试。
  • 聚合类型与可视化匹配(
    makeTimeseries
    vs
    summarize
    )。
  • 字段名称与注入器schema完全匹配。
组件创建:
  • Logo组件(markdown,
    h:2
    w:6
    )。
  • 标题组件(markdown,
    h:2
    w:18
    )。
  • 地图组件放置在
    y:2
    (执行摘要上方),
    w:24
    h:8
  • 分区分隔符(
    h:1
    ,带颜色)。
  • KPI组件(
    h:2
    ,每个分区下方);3-4个使用
    singleValue
    +阈值
    colorRules
    实现仪表盘效果。
  • 图表组件(
    h:4+
    ,KPI下方)。
  • 可视化类型混合: 整个仪表盘至少使用4种不同的图表类型(例如
    pieChart
    barChart
    categoricalBar
    honeycomb
    lineChart
    areaChart
    );避免全用环形图。
  • 所有
    barChart
    /
    categoricalBar
    查询使用
    makeTimeseries
    ,而非
    summarize by:{}
    fieldMapping
    包含
    timestamp:"timeframe"
    leftAxisValues
    leftAxisDimensions
  • 任何
    honeycomb
    组件已设置
    visualizationSettings.honeycomb.dataMappings.value
  • 任何非圆形图表已移除
    chartSettings.circleChartSettings
  • X位置一致(
    0, 6, 12, 18
    )。
  • Y间距最小化(
    +1
    +2
    )。
样式与验证:
  • 已应用分区颜色。
  • 图表
    legend.ratio
    为20-30。
  • 已设置
    categoryOverrides
    用于语义颜色。
  • 预览中无红色叉号组件。
  • Logo和地图组件渲染正确。

Phase 6 — Workflow & deployment (CRITICAL RULES)

阶段6 — 工作流与部署(关键规则)

The injector workflow is shared across all companies in a tenant. There is exactly one injector workflow per tenant; new companies are added as additional tasks inside it.
注入器工作流在租户中所有公司共享。每个租户只有一个注入器工作流;新公司作为额外任务添加到其中。

Step‑by‑step

分步操作

  1. Apply the dashboard:
    bash
    dtctl apply -f "dashboards/<Company>/<company>-dashboard-v1.json"
    Capture the returned dashboard ID.
    Envelope shape (REQUIRED):
    dtctl apply
    expects a wrapper:
    json
    { "id": "<uuid?>", "name": "<Company> | Operations Dashboard",
      "type": "dashboard", "isPrivate": false,
      "content": { "tiles": {...}, "layouts": {...}, "variables": [...],
                   "settings": {...}, "version": 21, ... } }
    Submitting just the
    content
    body imports tiles but creates an "Untitled dashboard" with name and ID detached. Re-applying with the wrapper fixes it in place (
    ACTION = updated
    ).
  2. Search for the existing injector workflow first:
    bash
    dtctl get workflows -o json --plain | \
      jq '.[] | select(.title | test("BizEvents Dashboard Generator|KPI Data Injector|injector"; "i"))'
    Prefer the workflow titled
    1.BizEvents Dashboard Generator
    . If multiple match, confirm with the user.
  3. If a workflow exists (the normal case):
    • dtctl get workflow <id> -o json --plain > .tmp/workflow.json
    • Append a new task keyed
      <company>_v1
      (or
      _v2
      on iteration).
    • Use a unique
      position.{x, y}
      — duplicates produce a 400 error.
    • Set
      predecessors: []
      so tasks run in parallel.
    • dtctl apply -f .tmp/workflow.json
  4. If no workflow exists (first run on a brand‑new tenant only):
    • Use
      reference/example_data_injector.workflow.json
      as the template.
    • Replace its single task with the new company's task; rename the workflow
      1.BizEvents Dashboard Generator
      .
    • dtctl apply -f
      it; capture the workflow ID.
  5. Execute and verify:
    bash
    dtctl exec workflow <id>
    dtctl describe workflow-execution <exec-id>   # wait for SUCCESS
    describe workflow-execution
    returns an empty
    tasks{}
    dict — to inspect the JS task's return value (totals, batches, errors) use:
    bash
    dtctl get wfe-task-result <exec-id> -t <taskName>
    The task name is required via the
    -t/--task
    flag, NOT positional.
  6. Verify ingestion:
    dql
    fetch bizevents
    | filter event.provider == "<company>.event.provider"
    | summarize total = count()
Never create a second injector workflow when one already exists.
  1. 应用仪表盘:
    bash
    dtctl apply -f "dashboards/<Company>/<company>-dashboard-v1.json"
    捕获返回的仪表盘ID。
    必填信封结构:
    dtctl apply
    需要一个包装器:
    json
    { "id": "<uuid?>", "name": "<Company> | 运营仪表盘",
      "type": "dashboard", "isPrivate": false,
      "content": { "tiles": {...}, "layouts": {...}, "variables": [...],
                   "settings": {...}, "version": 21, ... } }
    仅提交
    content
    主体会导入组件,但会创建一个“无标题仪表盘”,名称和ID分离。使用包装器重新应用可修复此问题(
    ACTION = updated
    )。
  2. 首先搜索现有注入器工作流:
    bash
    dtctl get workflows -o json --plain | \
      jq '.[] | select(.title | test("BizEvents Dashboard Generator|KPI Data Injector|injector"; "i"))'
    优先选择标题为
    1.BizEvents Dashboard Generator
    的工作流。如果有多个匹配项,请与用户确认。
  3. 如果工作流存在(正常情况):
    • dtctl get workflow <id> -o json --plain > .tmp/workflow.json
    • 添加一个新任务,键为
      <company>_v1
      (迭代时为
      _v2
      )。
    • 使用唯一
      position.{x, y}
      ——重复值会导致400错误。
    • 设置
      predecessors: []
      使任务并行运行。
    • dtctl apply -f .tmp/workflow.json
  4. 如果工作流不存在(仅在全新租户首次运行时):
    • 使用
      reference/example_data_injector.workflow.json
      作为模板。
    • 将其单个任务替换为新公司的任务;将工作流重命名为
      1.BizEvents Dashboard Generator
    • dtctl apply -f
      部署它;捕获工作流ID。
  5. 执行并验证:
    bash
    dtctl exec workflow <id>
    dtctl describe workflow-execution <exec-id>   # 等待SUCCESS(成功)状态
    describe workflow-execution
    返回空的
    tasks{}
    字典——要查看JS任务的返回值(总数、批量、错误),请使用:
    bash
    dtctl get wfe-task-result <exec-id> -t <taskName>
    必须通过
    -t/--task
    标志指定任务名称,而非位置参数。
  6. 验证数据摄入:
    dql
    fetch bizevents
    | filter event.provider == "<company>.event.provider"
    | summarize total = count()
当已有工作流存在时,绝不要创建第二个注入器工作流

Versioning

版本控制

  • First iteration:
    <company>-dashboard-v1.json
    , task
    <company>_v1
    .
  • Updates:
    <company>-dashboard-v2.json
    , task
    <company>_v2
    .
  • Never overwrite v1 files.

  • 首次迭代:
    <company>-dashboard-v1.json
    ,任务
    <company>_v1
  • 更新:
    <company>-dashboard-v2.json
    ,任务
    <company>_v2
  • 绝不覆盖v1文件。

Phase 7 — Documentation deliverables

阶段7 — 文档交付物

For every project, write into the company folder:
  • README.md
    — Project overview, file list, dashboard ID, workflow ID, task name, deployment commands.
  • LEARNINGS.md
    — DQL patterns, layout decisions, pitfalls, color scheme, anything reusable for the next project.
  • SALES-PITCH.md
    — 1‑page value proposition tailored to the company for the sales team.
LEARNINGS.md
template:
markdown
undefined
每个项目都要在公司文件夹中编写:
  • README.md
    ——项目概述、文件列表、仪表盘ID、工作流ID、任务名称、部署命令。
  • LEARNINGS.md
    ——DQL模式、布局决策、陷阱、配色方案、任何可复用的内容。
  • SALES-PITCH.md
    ——面向销售团队的、针对该公司的1页价值主张。
LEARNINGS.md
模板:
markdown
undefined

<Company> Dashboard Learnings

<Company> 仪表盘学习笔记

Date: <date> Version: v1
日期: <日期> 版本: v1

DQL Patterns Used

使用的DQL模式

Tile TypeDQL PatternNotes
组件类型DQL模式备注

Layout Decisions

布局决策

  • Header, dividers, KPI rows, chart rows...
  • 页眉、分隔符、KPI行、图表行...

Pitfalls Hit

遇到的陷阱

  1. ...
  1. ...

Color Scheme

配色方案

  • Section:
    #hex

---
  • 分区:
    #hex

---

Phase 8 — Quality gate (run before declaring done)

阶段8 — 质量门(完成前运行)

  • Logo renders.
  • All section dividers show correct colors.
  • No red‑X tiles.
  • Every KPI tile has data.
  • Every chart shows legends/labels.
  • Map tile is populated with cluster/region/site coordinates.
  • Layout is compact (no excessive whitespace).
  • Workflow execution finished SUCCESS.
  • 3,000+ events ingested per run.
  • README.md
    ,
    LEARNINGS.md
    ,
    SALES-PITCH.md
    all present.

  • Logo可正常渲染。
  • 所有分区分隔符显示正确颜色。
  • 无红色叉号组件。
  • 每个KPI组件都有数据。
  • 每个图表都显示图例/标签。
  • 地图组件已填充集群/区域/站点坐标。
  • 布局紧凑(无过多空白)。
  • 工作流执行完成状态为SUCCESS(成功)。
  • 每次运行摄入3000+条事件。
  • README.md
    LEARNINGS.md
    SALES-PITCH.md
    均已存在。

Key principles

核心原则

  1. Markdown formatting is critical — pure markdown only, no HTML.
  2. Logo = professional touch — every dashboard branded.
  3. Charts need space
    h:4
    minimum.
  4. Test before deploy — DQL in the editor first.
  5. Document everything
    LEARNINGS.md
    is the knowledge capital.
  6. Consistency breeds quality — follow the example shape exactly.
  7. One injector workflow per tenant — always add a task, never duplicate.

  1. Markdown格式至关重要——仅使用纯markdown,不使用HTML。
  2. Logo是专业的体现——每个仪表盘都要品牌化。
  3. 图表需要足够空间——高度至少
    h:4
  4. 部署前测试——先在编辑器中测试DQL。
  5. 记录所有内容——
    LEARNINGS.md
    是知识资产。
  6. 一致性造就质量——严格遵循示例结构。
  7. 每个租户一个注入器工作流——始终添加任务,绝不重复创建。

What the agent must NOT do

Agent绝对不能做的事

  • Do not invent dashboard IDs, workflow IDs, or URLs — always use values returned by
    dtctl
    .
  • Do not create a second injector workflow when one exists.
  • Do not skip the map tile.
  • Do not push commits or open PRs unless asked.
  • Do not run destructive
    dtctl delete
    commands without explicit user confirmation.
  • Do not attempt to install or configure
    dtctl
    .
  • 不要自行生成仪表盘ID、工作流ID或URL——始终使用
    dtctl
    返回的值。
  • 已有工作流存在时,不要创建第二个注入器工作流。
  • 不要跳过地图组件。
  • 除非被要求,否则不要推送提交或打开PR。
  • 未经用户明确确认,不要运行破坏性的
    dtctl delete
    命令。
  • 不要尝试安装或配置
    dtctl