kibana-vega by elastic/agent-skills
npx skills add https://github.com/elastic/agent-skills --skill kibana-vega使用 ES|QL 数据源创建和管理 Kibana 仪表板及 Vega 可视化。
Vega 是一种声明式可视化语法,用于在 Kibana 中创建自定义图表。结合 ES|QL 查询,它能够实现超越标准 Kibana 图表的高度定制化可视化。
重要版本要求: 此技能严格支持 ES|QL 数据源,并要求 Serverless Kibana 或 9.4+ (SNAPSHOT) 版本。在旧版本或使用旧的 Lucene/KQL 数据源定义时,它将无法可靠工作。
Kibana 连接通过环境变量配置。运行 node scripts/kibana-vega.js test 来验证连接。如果测试失败,向用户建议以下设置选项,然后停止。在成功通过连接测试之前,不要尝试进一步探索。
export KIBANA_CLOUD_ID="deployment-name:base64encodedcloudid"
export KIBANA_API_KEY="base64encodedapikey"
export KIBANA_URL="https://your-kibana:5601"
export KIBANA_API_KEY="base64encodedapikey"
export KIBANA_URL="https://your-kibana:5601"
export KIBANA_USERNAME="elastic"
export KIBANA_PASSWORD="changeme"
对于本地开发和测试,使用 通过 Docker 或 Podman 快速启动 Elasticsearch 和 Kibana:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
curl -fsSL https://elastic.co/start-local | sh
安装完成后,Elasticsearch 运行在 http://localhost:9200,Kibana 运行在 http://localhost:5601。该脚本为 elastic 用户生成一个随机密码,存储在创建的 elastic-start-local 文件夹内的 .env 文件中。
要为这个技能配置环境变量,请加载 .env 文件并导出连接设置:
source elastic-start-local/.env
export KIBANA_URL="$KB_LOCAL_URL"
export KIBANA_USERNAME="elastic"
export KIBANA_PASSWORD="$ES_LOCAL_PASSWORD"
然后运行 node scripts/kibana-vega.js test 来验证连接。
export KIBANA_INSECURE="true"
# 测试连接
node scripts/kibana-vega.js test
# 直接从 stdin 创建可视化(无需中间文件)
echo '<json-spec>' | node scripts/kibana-vega.js visualizations create "My Chart" -
# 获取可视化规范以供审阅/修改
node scripts/kibana-vega.js visualizations get <vis-id>
# 从 stdin 更新可视化
echo '<json-spec>' | node scripts/kibana-vega.js visualizations update <vis-id> -
# 创建仪表板
node scripts/kibana-vega.js dashboards create "My Dashboard"
# 添加带有网格位置的可视化
node scripts/kibana-vega.js dashboards add-panel <dashboard-id> <vis-id> --x 0 --y 0 --w 24 --h 15
# 从 stdin 应用完整布局
echo '<layout-json>' | node scripts/kibana-vega.js dashboards apply-layout <dashboard-id> -
注意: 使用 - 作为文件参数以从 stdin 读取 JSON。这支持无需中间文件直接创建规范。
重要提示:始终使用正确的 JSON 格式(不是带有三引号的 HJSON),以避免解析错误。
{
"$schema": "https://vega.github.io/schema/vega-lite/v6.json",
"title": "My Chart",
"autosize": { "type": "fit", "contains": "padding" },
"config": {
"axis": { "domainColor": "#444", "tickColor": "#444" },
"view": { "stroke": null }
},
"data": {
"url": {
"%type%": "esql",
"query": "FROM logs-* | STATS count = COUNT() BY status | RENAME status AS category"
}
},
"mark": { "type": "bar", "color": "#6092C0" },
"encoding": {
"x": { "field": "category", "type": "nominal" },
"y": { "field": "count", "type": "quantitative" }
}
}
| 属性 | 描述 | | --------------------------- | ------------------------------------------ | --------- | | %type%: "esql" | 必需。使用 ES | QL 解析器 | | %context%: true | 应用仪表板过滤器 | | %timefield%: "@timestamp" | 启用带有 ?_tstart/?_tend 的时间范围 |
# 直接从 JSON 创建可视化
echo '{"$schema":"https://vega.github.io/schema/vega-lite/v6.json",...}' | \
node scripts/kibana-vega.js visualizations create "My Chart" -
# 更新可视化
echo '{"$schema":...}' | node scripts/kibana-vega.js visualizations update <id> -
# 直接应用布局
echo '{"panels":[{"visualization":"<id>","x":0,"y":0,"w":24,"h":10}]}' | \
node scripts/kibana-vega.js dashboards apply-layout <dash-id> -
Kibana 仪表板使用 48 列网格:
| 宽度 | 列数 | 使用场景 |
|---|---|---|
| 全宽 | 48 | 时间线、热力图、宽图表 |
| 半宽 | 24 | 并排比较 |
| 三分之一宽 | 16 | 三列布局 |
| 四分之一宽 | 12 | KPI 指标、小型摘要 |
主要信息必须无需滚动即可见。
| 分辨率 | 可见高度 | 布局预算 |
|---|---|---|
| 1080p | ~30 单位 | 2 行:h:10 + h:12 |
| 1440p | ~40 单位 | 3 行:h:12 + h:12 + h:12 |
高度指南:
h: 10 — 紧凑型条形图(≤7 个项目),适合首屏h: 12-13 — 标准图表,时间线h: 15+ — 详细视图,用于首屏以下区域┌───────────────────────┬───────────────────────┐ y:0
│ 当前状态 A │ 当前状态 B │ h:10 (紧凑)
├───────────────────────┴───────────────────────┤ y:10
│ 主要时间线 │ h:12 (主要趋势)
├ ─ ─ ─ ─ ─ ─ ─ 首屏线 ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤ y:22 (1080p 首屏线)
│ 次要时间线 │ h:12 (首屏以下可接受)
├───────────────────────┬───────────────────────┤ y:34
│ 补充信息 1 │ 补充信息 2 │ h:10
└───────────────────────┴───────────────────────┘
# 第 1 行:两个紧凑的半宽图表(首屏)
node scripts/kibana-vega.js dashboards add-panel $DASH $VIS1 --x 0 --y 0 --w 24 --h 10
node scripts/kibana-vega.js dashboards add-panel $DASH $VIS2 --x 24 --y 0 --w 24 --h 10
# 第 2 行:全宽时间线(首屏)
node scripts/kibana-vega.js dashboards add-panel $DASH $VIS3 --x 0 --y 10 --w 48 --h 12
# 第 3 行:首屏以下内容
node scripts/kibana-vega.js dashboards add-panel $DASH $VIS4 --x 0 --y 22 --w 48 --h 12
创建 layout.json:
{
"title": "My Dashboard",
"panels": [
{ "visualization": "<vis-id-1>", "x": 0, "y": 0, "w": 24, "h": 10 },
{ "visualization": "<vis-id-2>", "x": 24, "y": 0, "w": 24, "h": 10 },
{ "visualization": "<vis-id-3>", "x": 0, "y": 10, "w": 48, "h": 12 },
{ "visualization": "<vis-id-4>", "x": 0, "y": 22, "w": 48, "h": 12 }
]
}
应用它:
node scripts/kibana-vega.js dashboards apply-layout <dashboard-id> layout.json
使用 JSON,而不是 HJSON 三引号 — ''' 多行字符串会导致 Kibana 解析错误;使用带转义引号 \" 的单行查询
重命名带点的字段 — room.name 会破坏 Vega(被解释为嵌套路径);使用 ES|QL RENAME room.name AS room
不要设置宽度/高度 — 使用 autosize: { type: fit, contains: padding }
在坐标轴上设置 labelLimit — 水平条形图标签会被截断;使用 axis: { "labelLimit": 150 }
按值对条形排序 — 在 ES|QL 中使用 SORT field DESC 预排序,并在编码中使用 sort: null(保持数据顺序);避免在分层规范(条形 + 文本标签)中使用 sort: "-x",因为它会导致“冲突的排序属性”警告
时间轴:无旋转标签 — 使用 axis: { "labelAngle": 0, "tickCount": 8 },让 Vega 自动格式化日期
描述性标题替代坐标轴标题 — 好的标题/副标题使坐标轴标题变得多余;在坐标轴上使用 title: null
谨慎使用颜色 — 颜色是宝贵的视觉属性;对于位置已经编码值的条形图,使用单一默认颜色 (#6092C0);保留颜色编码用于分类区分(例如,时间序列中的多条线)
深色主题兼容性 — 始终包含配置以避免亮白色边框:
"config": {
"axis": { "domainColor": "#444", "tickColor": "#444" },
"view": { "stroke": null }
}
# 仪表板
node scripts/kibana-vega.js dashboards list [search]
node scripts/kibana-vega.js dashboards get <id>
node scripts/kibana-vega.js dashboards create <title>
node scripts/kibana-vega.js dashboards delete <id>
node scripts/kibana-vega.js dashboards add-panel <dash-id> <vis-id> [--x N] [--y N] [--w N] [--h N]
node scripts/kibana-vega.js dashboards apply-layout <dash-id> <file|->
# 可视化(使用 - 代替文件从 stdin 读取)
node scripts/kibana-vega.js visualizations list [vega]
node scripts/kibana-vega.js visualizations get <id>
node scripts/kibana-vega.js visualizations create <title> <file|->
node scripts/kibana-vega.js visualizations update <id> <file|->
node scripts/kibana-vega.js visualizations delete <id>
| 错误 | 解决方案 |
|---|---|
| "End of input while parsing an object" | 不要使用 HJSON ''' 三引号;使用带有单行查询的 JSON |
| 标签显示 "undefined" | 重命名带点的字段:RENAME room.name AS room |
| 条形不可见 / 未渲染 | 移除复杂的 scale.domain,使用更简单的配色方案 |
| Y 轴标签被截断 | 在编码中添加 axis: { "labelLimit": 150 } |
| 面板垂直堆叠 | 使用 --x --y --w --h 选项或 apply-layout 命令 |
| "width/height ignored" | 移除尺寸设置,使用 autosize |
| 深色主题上出现亮白色边框 | 添加 config: { "view": { "stroke": null }, "axis": { "domainColor": "#444", "tickColor": "#444" } } |
| "401 Unauthorized" | 检查 KIBANA_USERNAME/PASSWORD |
| "conflicting sort properties" | 不要在分层规范中使用 sort: "-x";在 ES |
| "404 Not Found" | 验证仪表板/可视化 ID |
每周安装量
140
代码仓库
GitHub Stars
89
首次出现
11 天前
安全审计
安装于
cursor125
github-copilot118
opencode117
gemini-cli117
codex117
amp116
Create and manage Kibana dashboards and Vega visualizations with ES|QL data sources.
Vega is a declarative visualization grammar for creating custom charts in Kibana. Combined with ES|QL queries, it enables highly customized visualizations beyond standard Kibana charts.
Important Version Requirement: This skill strictly supports ES|QL data sources and requires Serverless Kibana or version 9.4+ (SNAPSHOT). It will not work reliably on older versions or with older Lucene/KQL data source definitions.
Kibana connection is configured via environment variables. Run node scripts/kibana-vega.js test to verify the connection. If the test fails, suggest these setup options to the user, then stop. Do not try to explore further until a successful connection test.
export KIBANA_CLOUD_ID="deployment-name:base64encodedcloudid"
export KIBANA_API_KEY="base64encodedapikey"
export KIBANA_URL="https://your-kibana:5601"
export KIBANA_API_KEY="base64encodedapikey"
export KIBANA_URL="https://your-kibana:5601"
export KIBANA_USERNAME="elastic"
export KIBANA_PASSWORD="changeme"
For local development and testing, use start-local to quickly spin up Elasticsearch and Kibana using Docker or Podman:
curl -fsSL https://elastic.co/start-local | sh
After installation completes, Elasticsearch runs at http://localhost:9200 and Kibana at http://localhost:5601. The script generates a random password for the elastic user, stored in the .env file inside the created elastic-start-local folder.
To configure the environment variables for this skill, source the .env file and export the connection settings:
source elastic-start-local/.env
export KIBANA_URL="$KB_LOCAL_URL"
export KIBANA_USERNAME="elastic"
export KIBANA_PASSWORD="$ES_LOCAL_PASSWORD"
Then run node scripts/kibana-vega.js test to verify the connection.
export KIBANA_INSECURE="true"
# Test connection
node scripts/kibana-vega.js test
# Create visualization directly from stdin (no intermediate file needed)
echo '<json-spec>' | node scripts/kibana-vega.js visualizations create "My Chart" -
# Get visualization spec for review/modification
node scripts/kibana-vega.js visualizations get <vis-id>
# Update visualization from stdin
echo '<json-spec>' | node scripts/kibana-vega.js visualizations update <vis-id> -
# Create dashboard
node scripts/kibana-vega.js dashboards create "My Dashboard"
# Add visualization with grid position
node scripts/kibana-vega.js dashboards add-panel <dashboard-id> <vis-id> --x 0 --y 0 --w 24 --h 15
# Apply a complete layout from stdin
echo '<layout-json>' | node scripts/kibana-vega.js dashboards apply-layout <dashboard-id> -
Note: Use - as the file argument to read JSON from stdin. This enables direct spec creation without intermediate files.
IMPORTANT : Always use proper JSON format (not HJSON with triple quotes) to avoid parse errors.
{
"$schema": "https://vega.github.io/schema/vega-lite/v6.json",
"title": "My Chart",
"autosize": { "type": "fit", "contains": "padding" },
"config": {
"axis": { "domainColor": "#444", "tickColor": "#444" },
"view": { "stroke": null }
},
"data": {
"url": {
"%type%": "esql",
"query": "FROM logs-* | STATS count = COUNT() BY status | RENAME status AS category"
}
},
"mark": { "type": "bar", "color": "#6092C0" },
"encoding": {
"x": { "field": "category", "type": "nominal" },
"y": { "field": "count", "type": "quantitative" }
}
}
| Property | Description | | --------------------------- | ------------------------------------------ | --------- | | %type%: "esql" | Required. Use ES | QL parser | | %context%: true | Apply dashboard filters | | %timefield%: "@timestamp" | Enable time range with ?_tstart/?_tend |
# Create visualization directly from JSON
echo '{"$schema":"https://vega.github.io/schema/vega-lite/v6.json",...}' | \
node scripts/kibana-vega.js visualizations create "My Chart" -
# Update visualization
echo '{"$schema":...}' | node scripts/kibana-vega.js visualizations update <id> -
# Apply layout directly
echo '{"panels":[{"visualization":"<id>","x":0,"y":0,"w":24,"h":10}]}' | \
node scripts/kibana-vega.js dashboards apply-layout <dash-id> -
Kibana dashboards use a 48-column grid :
| Width | Columns | Use Case |
|---|---|---|
| Full | 48 | Timelines, heatmaps, wide charts |
| Half | 24 | Side-by-side comparisons |
| Third | 16 | Three-column layouts |
| Quarter | 12 | KPI metrics, small summaries |
Primary information must be visible without scrolling.
| Resolution | Visible Height | Layout Budget |
|---|---|---|
| 1080p | ~30 units | 2 rows: h:10 + h:12 |
| 1440p | ~40 units | 3 rows: h:12 + h:12 + h:12 |
Height guidelines:
h: 10 — Compact bar charts (≤7 items), fits above foldh: 12-13 — Standard charts, timelinesh: 15+ — Detailed views, use below fold┌───────────────────────┬───────────────────────┐ y:0
│ Current State A │ Current State B │ h:10 (compact)
├───────────────────────┴───────────────────────┤ y:10
│ Primary Timeline │ h:12 (main trend)
├ ─ ─ ─ ─ ─ ─ ─ FOLD ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤ y:22 (1080p fold)
│ Secondary Timeline │ h:12 (below fold OK)
├───────────────────────┬───────────────────────┤ y:34
│ Complementary 1 │ Complementary 2 │ h:10
└───────────────────────┴───────────────────────┘
# Row 1: Two compact half-width charts (above fold)
node scripts/kibana-vega.js dashboards add-panel $DASH $VIS1 --x 0 --y 0 --w 24 --h 10
node scripts/kibana-vega.js dashboards add-panel $DASH $VIS2 --x 24 --y 0 --w 24 --h 10
# Row 2: Full-width timeline (above fold)
node scripts/kibana-vega.js dashboards add-panel $DASH $VIS3 --x 0 --y 10 --w 48 --h 12
# Row 3: Below fold content
node scripts/kibana-vega.js dashboards add-panel $DASH $VIS4 --x 0 --y 22 --w 48 --h 12
Create layout.json:
{
"title": "My Dashboard",
"panels": [
{ "visualization": "<vis-id-1>", "x": 0, "y": 0, "w": 24, "h": 10 },
{ "visualization": "<vis-id-2>", "x": 24, "y": 0, "w": 24, "h": 10 },
{ "visualization": "<vis-id-3>", "x": 0, "y": 10, "w": 48, "h": 12 },
{ "visualization": "<vis-id-4>", "x": 0, "y": 22, "w": 48, "h": 12 }
]
}
Apply it:
node scripts/kibana-vega.js dashboards apply-layout <dashboard-id> layout.json
Use JSON, not HJSON triple-quotes — ''' multi-line strings cause parse errors in Kibana; use single-line queries with escaped quotes \"
Rename dotted fields — room.name breaks Vega (interpreted as nested path); use ES|QL RENAME room.name AS room
Don't set width/height — use autosize: { type: fit, contains: padding }
Set labelLimit on axes — horizontal bar chart labels truncate; use axis: { "labelLimit": 150 }
Sort bars by value — pre-sort in ES|QL with SORT field DESC and use in encoding (preserves data order); avoid in layered specs (bar + text labels) as it causes "conflicting sort properties" warnings
# Dashboards
node scripts/kibana-vega.js dashboards list [search]
node scripts/kibana-vega.js dashboards get <id>
node scripts/kibana-vega.js dashboards create <title>
node scripts/kibana-vega.js dashboards delete <id>
node scripts/kibana-vega.js dashboards add-panel <dash-id> <vis-id> [--x N] [--y N] [--w N] [--h N]
node scripts/kibana-vega.js dashboards apply-layout <dash-id> <file|->
# Visualizations (use - for stdin instead of file)
node scripts/kibana-vega.js visualizations list [vega]
node scripts/kibana-vega.js visualizations get <id>
node scripts/kibana-vega.js visualizations create <title> <file|->
node scripts/kibana-vega.js visualizations update <id> <file|->
node scripts/kibana-vega.js visualizations delete <id>
| Error | Solution |
|---|---|
| "End of input while parsing an object" | Don't use HJSON ''' triple-quotes; use JSON with single-line queries |
| Labels show "undefined" | Rename dotted fields: RENAME room.name AS room |
| Bars invisible / not rendering | Remove complex scale.domain, use simpler color schemes |
| Y-axis labels truncated | Add axis: { "labelLimit": 150 } to encoding |
| Panels stacked vertically | Use --x --y --w --h options or apply-layout command |
Weekly Installs
140
Repository
GitHub Stars
89
First Seen
11 days ago
Security Audits
Gen Agent Trust HubFailSocketPassSnykWarn
Installed on
cursor125
github-copilot118
opencode117
gemini-cli117
codex117
amp116
Excel财务建模规范与xlsx文件处理指南:专业格式、零错误公式与数据分析
45,000 周安装
为Web应用添加MCP App支持:单一代码库实现独立运行与Claude内嵌渲染
226 周安装
execute-plan:AI代理技能,严格执行自动化计划与验证工作流
229 周安装
Pinia官方状态管理库:Vue.js类型安全状态管理,支持Options/Composition API
230 周安装
全栈可观测性与监控方案:Pino日志、Sentry错误追踪、Vercel分析集成
229 周安装
GitNexus 影响分析工具:代码变更风险评估与依赖关系可视化
232 周安装
NewAPI:开源统一AI网关平台,聚合OpenAI/Claude/Gemini接口,管理模型与令牌
235 周安装
sort: nullsort: "-x"Time axis: no rotated labels — use axis: { "labelAngle": 0, "tickCount": 8 }, let Vega auto-format dates
Descriptive titles replace axis titles — good title/subtitle makes axis titles redundant; use title: null on axes
Use color sparingly — color is a precious visual attribute; use a single default color (#6092C0) for bar charts where position already encodes value; reserve color encoding for categorical distinction (e.g., multiple lines in a time series)
Dark theme compatibility — always include config to avoid bright white borders:
"config": {
"axis": { "domainColor": "#444", "tickColor": "#444" },
"view": { "stroke": null }
}
| "width/height ignored" | Remove dimensions, use autosize |
| Bright white borders on dark theme | Add config: { "view": { "stroke": null }, "axis": { "domainColor": "#444", "tickColor": "#444" } } |
| "401 Unauthorized" | Check KIBANA_USERNAME/PASSWORD |
| "conflicting sort properties" | Don't use sort: "-x" in layered specs; pre-sort in ES |
| "404 Not Found" | Verify dashboard/visualization ID |