From 4b493e98c6c67751d348687a5c7a93c688e6bc75 Mon Sep 17 00:00:00 2001 From: daniel-edgedelta Date: Fri, 6 Mar 2026 16:23:09 -0800 Subject: [PATCH 1/2] feat: add edgedelta-dashboards plugin Adds the edgedelta-dashboards plugin as the fourth plugin in the Edge Delta official marketplace. The plugin combines an MCP server integration with a comprehensive skill for AI-assisted dashboard management. Plugin components: - .mcp.json: Connects to ghcr.io/edgedelta/edgedelta-mcp-server via Docker stdio transport. Auth via ED_API_TOKEN and ED_ORG_ID env vars with no credentials stored in the plugin. - plugin.json: Plugin manifest with skills and mcpConfig references. - SKILL.md: v4 schema knowledge, MCP builder workflow guidance, widget types, grid layout rules, and validation patterns. - 6 reference files: troubleshooting, create-from-scratch, schema reference, validation guide, batch operations, export-and-modify. All rewritten for MCP tool usage (Python CLI references removed). - 3 YAML asset templates in v4 format: quickstart, system-metrics, logs-analysis. - marketplace.json entry added. Security: No credentials, API tokens, org IDs, or internal paths present in any plugin file. ED_API_TOKEN and ED_ORG_ID appear only as environment variable names passed via Docker -e flags. --- .claude-plugin/marketplace.json | 14 + .../.claude-plugin/plugin.json | 15 + plugins/edgedelta-dashboards/.mcp.json | 17 + plugins/edgedelta-dashboards/README.md | 66 +++ .../skills/edgedelta-dashboards/SKILL.md | 469 +++++++++++++++ .../assets/logs-analysis.yaml | 151 +++++ .../assets/quickstart-dashboard.yaml | 106 ++++ .../assets/system-metrics.yaml | 108 ++++ .../references/batch-operations.md | 305 ++++++++++ .../references/create-from-scratch.md | 434 ++++++++++++++ .../references/export-and-modify.md | 394 +++++++++++++ .../references/schema-reference.md | 548 ++++++++++++++++++ .../references/troubleshooting.md | 432 ++++++++++++++ .../references/validation-guide.md | 530 +++++++++++++++++ 14 files changed, 3589 insertions(+) create mode 100644 plugins/edgedelta-dashboards/.claude-plugin/plugin.json create mode 100644 plugins/edgedelta-dashboards/.mcp.json create mode 100644 plugins/edgedelta-dashboards/README.md create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/SKILL.md create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/logs-analysis.yaml create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/system-metrics.yaml create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/batch-operations.md create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/create-from-scratch.md create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/export-and-modify.md create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/schema-reference.md create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/troubleshooting.md create mode 100644 plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/validation-guide.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 253c39d..c51029d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -48,6 +48,20 @@ "homepage": "https://docs.edgedelta.com", "tags": ["reference", "processors", "sources", "destinations", "pipeline", "observability"], "strict": false + }, + { + "name": "edgedelta-dashboards", + "description": "Create, update, delete, and manage EdgeDelta dashboards via MCP. Includes v4 schema knowledge, widget builder workflow, and validation guidance.", + "version": "1.0.0", + "author": { + "name": "Edge Delta", + "email": "plugins@edgedelta.com" + }, + "source": "./plugins/edgedelta-dashboards", + "category": "development", + "homepage": "https://docs.edgedelta.com", + "tags": ["dashboards", "observability", "monitoring", "mcp", "visualization"], + "strict": false } ] } diff --git a/plugins/edgedelta-dashboards/.claude-plugin/plugin.json b/plugins/edgedelta-dashboards/.claude-plugin/plugin.json new file mode 100644 index 0000000..c241ee4 --- /dev/null +++ b/plugins/edgedelta-dashboards/.claude-plugin/plugin.json @@ -0,0 +1,15 @@ +{ + "name": "edgedelta-dashboards", + "version": "1.0.0", + "description": "Create, update, delete, and manage EdgeDelta dashboards via MCP. Includes v4 schema knowledge for AI-assisted dashboard design.", + "author": { + "name": "Edge Delta", + "email": "plugins@edgedelta.com" + }, + "homepage": "https://docs.edgedelta.com", + "repository": "https://github.com/edgedelta/claude-code-plugins", + "license": "MIT", + "keywords": ["edgedelta", "dashboards", "observability", "monitoring", "visualization"], + "skills": ["./skills/edgedelta-dashboards"], + "mcpConfig": "./.mcp.json" +} diff --git a/plugins/edgedelta-dashboards/.mcp.json b/plugins/edgedelta-dashboards/.mcp.json new file mode 100644 index 0000000..a64ae04 --- /dev/null +++ b/plugins/edgedelta-dashboards/.mcp.json @@ -0,0 +1,17 @@ +{ + "mcpServers": { + "edgedelta": { + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "-e", + "ED_ORG_ID", + "-e", + "ED_API_TOKEN", + "ghcr.io/edgedelta/edgedelta-mcp-server:latest" + ] + } + } +} diff --git a/plugins/edgedelta-dashboards/README.md b/plugins/edgedelta-dashboards/README.md new file mode 100644 index 0000000..146f3bb --- /dev/null +++ b/plugins/edgedelta-dashboards/README.md @@ -0,0 +1,66 @@ +# EdgeDelta Dashboards Plugin + +Create, update, delete, and manage EdgeDelta dashboards directly from Claude Code. Includes AI-assisted dashboard design with full v4 schema knowledge, widget builder workflow, and validation guidance. + +## Features + +- **List & inspect** dashboards across your organization +- **Create dashboards** using a guided widget builder workflow or raw JSON +- **Update & delete** existing dashboards +- **V4 schema knowledge** — Claude understands widget types, grid layout rules, and visualizer options +- **Built-in validation guidance** — catches common errors before API calls + +## Prerequisites + +1. **Docker** installed and running ([get Docker](https://docs.docker.com/get-docker/)) +2. **EdgeDelta API token** — [create one here](https://docs.edgedelta.com/api-tokens/) +3. **EdgeDelta organization ID** — [find it here](https://docs.edgedelta.com/my-organization/) + +> **Note:** Dashboard management tools (create, update, delete, assemble) require EdgeDelta MCP Server with dashboard support, available in the next MCP server release. The get_all_dashboards and get_dashboard read tools are available today. + +## Setup + +Set your credentials as environment variables before starting Claude Code: + +``` +export ED_API_TOKEN="your-api-token" +export ED_ORG_ID="your-org-id" +``` + +Or add them to your shell profile (~/.zshrc, ~/.bashrc) for persistence. + +## Available MCP Tools + +| Tool | Description | +|------|-------------| +| get_all_dashboards | List all dashboards in your organization | +| get_dashboard | Get full configuration for a specific dashboard | +| create_dashboard | Create a new dashboard from a JSON definition | +| update_dashboard | Update an existing dashboard | +| delete_dashboard | Permanently delete a dashboard | +| get_dashboard_schema | Get the v4 widget schema (filter by category) | +| create_widget | Build and validate a widget configuration | +| assemble_dashboard | Combine widget configs and create a dashboard in one call | + +## Usage Examples + +List all dashboards: "Show me all dashboards in my EdgeDelta organization" +Create a dashboard: "Create a dashboard with a line chart showing error rates over time and a big number showing total log count" +Export and modify: "Export the API Monitoring dashboard so I can add a new widget to it" + +## Dashboard Templates + +This plugin includes starter templates in skills/edgedelta-dashboards/assets/: +- quickstart-dashboard.yaml — Minimal single-widget example +- system-metrics.yaml — Multi-panel metrics dashboard +- logs-analysis.yaml — Log-focused dashboard + +## Authentication + +This plugin uses EdgeDelta API token authentication. The MCP server reads ED_API_TOKEN and ED_ORG_ID from your environment — no credentials are stored in the plugin. + +## Resources + +- EdgeDelta Documentation: https://docs.edgedelta.com +- EdgeDelta MCP Server: https://github.com/edgedelta/edgedelta-mcp-server +- EdgeDelta API Tokens: https://docs.edgedelta.com/api-tokens/ diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/SKILL.md b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/SKILL.md new file mode 100644 index 0000000..8fa4cef --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/SKILL.md @@ -0,0 +1,469 @@ +--- +name: edgedelta-dashboards +version: 1.1.0 +last_updated: 2025-10-21 +description: Create, update, delete, and manage EdgeDelta dashboards via the EdgeDelta MCP server. Use when users need to build monitoring dashboards, add widgets, visualize metrics or logs, export dashboard configurations, or work with the EdgeDelta dashboard schema. Recognizes phrases like "build a dashboard", "add a widget", "dashboard schema", "visualize my metrics", "export dashboard", "EdgeDelta panel", "create a chart", "update my dashboard". +--- + +# EdgeDelta Dashboard Management Skill + +This skill provides expert guidance for managing EdgeDelta dashboards using the EdgeDelta MCP server. Activate this skill when users need to work with EdgeDelta dashboards in any capacity. + +## When to Activate This Skill + +Activate this skill when the user mentions: +- Creating, updating, exporting, or deleting EdgeDelta dashboards +- Dashboard templates or YAML/JSON configurations +- EdgeDelta visualization, widgets, or panels +- Dashboard validation errors or schema issues +- Batch dashboard operations or migrations +- "edgedelta-dashboards" CLI tool +- Dashboard authentication or login issues + +## Prerequisites and Setup + +### Required Environment Variables + +Set your EdgeDelta credentials in your shell: + +```bash +export ED_API_TOKEN="your-api-token" +export ED_ORG_ID="your-org-id" +``` + +Add to `~/.zshrc` or `~/.bashrc` for persistence. + +Get your API token: https://docs.edgedelta.com/api-tokens/ +Get your org ID: https://docs.edgedelta.com/my-organization/ + +See the Troubleshooting section below for auth error resolution. + +### Docker Requirement + +The EdgeDelta MCP server runs via Docker. Ensure Docker is installed and running: + +```bash +docker --version +``` + +The MCP server starts automatically when Claude Code connects to it. + +## Core Operations + +### 1. List Dashboards + +Use the `get_all_dashboards` tool to list all dashboards in the organization: + +- Call `get_all_dashboards` to retrieve dashboard names and IDs +- Pass `include_definitions: true` to also retrieve full dashboard definitions + +**Use Case**: Discovery, inventory, finding dashboard IDs before other operations + +### 2. Get a Dashboard + +Use the `get_dashboard` tool to retrieve a single dashboard: + +- Requires `dashboard_id` (obtain from `get_all_dashboards` first) +- Returns the full dashboard definition + +**Use Case**: Inspecting existing dashboard config before modification, backup, template creation + +### 3. Create Dashboard + +Two workflows available: + +**Builder workflow (recommended)**: +1. Call `get_dashboard_schema` to discover available widget types and parameters +2. Call `create_widget` for each widget in the dashboard +3. Call `assemble_dashboard` with all widget configs — handles layout automatically + +**Direct workflow**: +- Call `create_dashboard` with a raw JSON definition + +**Use Case**: New dashboards, standardized deployments, infrastructure as code + +### 4. Update Dashboard + +Use the `update_dashboard` tool: + +- Requires `dashboard_id` + a full JSON definition +- Workflow: call `get_dashboard` to export first, modify the definition locally, then call `update_dashboard` + +**Use Case**: Dashboard modifications, standardization, bulk updates + +### 5. Delete Dashboard + +Use the `delete_dashboard` tool: + +- Requires `dashboard_id` +- This operation is irreversible — confirm with the user before proceeding + +**Use Case**: Cleanup, decommissioning, removing test dashboards + +## MCP Dashboard Builder Workflow + +The builder workflow is the recommended way to create dashboards. It guides Claude through widget-by-widget construction with validation at each step. + +### Workflow Steps + +1. **Discover widget types**: Call `get_dashboard_schema` to understand available widget types, data source types, and parameters. Filter by category to reduce response size: `timeseries`, `scalar`, `aggregates`, `other`, `layout`. + +2. **Create each widget**: Call `create_widget` for each widget. Returns a validated widget config or specific error messages if parameters are invalid. + +3. **Assemble and create**: Call `assemble_dashboard` with all widget configs. Handles grid layout automatically (2 widgets per row, 6 columns each, or use custom `column`/`row` position parameters). + +### When to Use Each Tool + +| Tool | When to Use | +|------|-------------| +| `get_dashboard_schema` + `create_widget` + `assemble_dashboard` | Creating new dashboards — provides validation and auto-layout | +| `create_dashboard` | Applying a pre-built JSON definition you already have | +| `update_dashboard` | Modifying an existing dashboard (export first, modify, then update) | +| `get_all_dashboards` | Discovery — finding dashboard IDs before get/update/delete | +| `get_dashboard` | Inspecting existing dashboard config before modification | + +### Auto-Layout Rules + +`assemble_dashboard` auto-positions widgets if `column`/`row` not specified: +- 2 widgets per row (6 columns each) +- 4 rows tall per widget by default +- Override with `column`, `column_span`, `row`, `row_span` parameters + +## Batch Operations + +The EdgeDelta MCP server currently supports individual dashboard operations. For bulk workflows: + +- **Export all dashboards**: Call `get_all_dashboards` with `include_definitions: true`, then save each definition to YAML/JSON files for version control +- **Create multiple dashboards**: Prepare JSON definitions and call `create_dashboard` for each +- **Migration**: Export with `get_all_dashboards`, modify definitions locally, re-create with `create_dashboard` + +## Dashboard Schema (v4) + +### Complete Dashboard Structure + +```yaml +dashboard_name: "My Dashboard" +description: "Dashboard description (optional)" +tags: + - tag1 + - tag2 +definition: + version: 4 + timeFilters: + lookback: "1h" # 15m, 30m, 1h, 3h, 6h, 12h, 24h, 7d, 30d + widgets: + - # Root widget (REQUIRED!) + id: "root" + type: "grid" + grid: "72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" + + - # Example viz widget + id: 1 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: + column: 1 # 1-12 (1-indexed) + columnSpan: 6 # Width in columns + row: 1 # 1+ (1-indexed) + rowSpan: 2 # Height in rows + displayOptions: + title: "Widget Title" + visualizer: + type: "bignumber" # See visualizer types below + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "*" +``` + +### Critical Schema Rules + +1. **Root Widget is MANDATORY** + - Every dashboard MUST have exactly one root widget + - Must have: `id: "root"`, `type: "grid"`, and `grid` property + - Standard grid: 12 columns × N rows (72px per row) + +2. **All non-root widgets MUST have `position`** + - type: "grid" + - targetId: "root" (or another container) + - area: {column, columnSpan, row, rowSpan} + +3. **Grid positioning is 1-indexed** (not 0-indexed!) + - Columns: 1-12 + - Rows: 1 to N + - Widget must fit: column + columnSpan ≤ 13 + +4. **Version must be 4** + +### Widget Types (6 total) + +- `viz`: Data visualizations (charts, graphs, stats) +- `markdown`: Rich text/HTML content +- `grid`: Layout container (required as root) +- `tabs`: Tab navigation container +- `variable-control`: Dashboard variable controls +- `empty`: Placeholder widget + +### Visualizer Types (24 total) + +**Single-value** (resultType: aggregate): +- `bignumber` - Large single metric +- `gauge` - Gauge chart + +**Multi-value** (resultType: aggregate): +- `pie`, `donut` - Circular charts +- `column` - Bar charts +- `radar` - Radar chart +- `treemap`, `sunburst` - Hierarchical views +- `sankey` - Flow diagram +- `bubble` - Bubble chart +- `list` - List view +- `geomap` - Geographic map + +**Timeseries** (resultType: timeseries): +- `line`, `area`, `bar` - Time series charts +- `scatter`, `step`, `smooth` - Specialized time series + +**Table**: +- `table` - Formatted table +- `raw-table` - Raw data table + +**Special**: +- `json` - JSON viewer +- `empty` - Placeholder + +### Data Source Types (7 total) + +- `metric`: Metric queries (e.g., `avg:cpu.percent{*}`) +- `log`: Log filter queries +- `trace`: Distributed tracing data +- `event`: Event data +- `pattern`: Log pattern analysis +- `formula`: Mathematical formulas (e.g., `A + B`) +- `empty`: Placeholder + +## Validation Error Handling + +The MCP server includes pre-upload validation. When validation fails, AI-friendly error messages are shown. + +### Common Validation Errors + +#### Missing Root Widget +``` +ERROR: Dashboard MUST have a root widget. Root widget MUST have: +id='root', type='grid', grid=''. + +FIX: Add a root grid widget as the first widget in the widgets array. +``` + +**Solution**: Always start widgets array with root widget: +```yaml +widgets: + - id: "root" + type: "grid" + grid: "72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" +``` + +#### Missing Position +``` +ERROR: Widget #1 is missing 'position' field. All non-root widgets MUST have a position. + +FIX: Add position: {'type': 'grid', 'targetId': 'root', 'area': {...}} to widget #1. +``` + +**Solution**: Add position to every non-root widget: +```yaml +position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 6 + row: 1 + rowSpan: 2 +``` + +#### Grid Boundary Violation +``` +ERROR: Widget extends beyond grid bounds: column 7 + span 8 = 15 +(exceeds standard 12-column grid). + +FIX: Reduce columnSpan or adjust column position to stay within 12 columns. +``` + +**Solution**: Ensure `column + columnSpan ≤ 13`: +```yaml +# BAD: 7 + 8 = 15 > 13 +area: + column: 7 + columnSpan: 8 + +# GOOD: 7 + 6 = 13 +area: + column: 7 + columnSpan: 6 +``` + +#### Invalid Version +``` +ERROR: Dashboard version must be 4, got: 3 +``` + +**Solution**: Always use version 4: +```yaml +definition: + version: 4 +``` + +## Template Creation Workflow + +When helping users create dashboards from scratch: + +### 1. Understand Requirements +Ask about: +- Dashboard purpose (metrics, logs, traces, mixed) +- Data sources (what metrics/logs are available) +- Layout preferences (number of panels, organization) +- Time range needs +- Target audience + +### 2. Start with Template +Offer to use one of these starting points: +- `quickstart-dashboard.yaml` - Minimal 1-widget example +- `system-metrics.yaml` - Multi-panel metrics dashboard +- `logs-analysis.yaml` - Log-focused dashboard + +Located in: `${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/` + +### 3. Customize Step-by-Step +Guide through: +1. Root widget setup (usually no changes needed) +2. First widget creation (layout, visualizer, data source) +3. Additional widgets (positioning, no overlaps) +4. Metadata (name, description, tags) +5. Time filters + +### 4. Validate Before Create +Always validate locally before attempting to create: +- Check root widget exists +- Verify all positions are valid +- Ensure grid boundaries respected +- Confirm data source queries are valid + +### 5. Create and Verify +Use `assemble_dashboard` (builder workflow) or `create_dashboard` (direct JSON), then verify in the EdgeDelta UI. + +## Best Practices + +### Dashboard Design +1. **Start with root widget** - Always the first widget in array +2. **Plan grid layout** - Sketch 12-column layout before coding +3. **Use consistent sizing** - Standard heights: 2, 3, 4 rows +4. **Avoid overlaps** - Grid positions should not conflict +5. **Logical grouping** - Related metrics together +6. **Responsive design** - Full-width widgets for mobile + +### Widget Layout +- **BigNumber/Gauge**: 2-4 columns wide, 2 rows tall +- **Charts**: 6-12 columns wide, 3-4 rows tall +- **Tables**: 12 columns wide, 4+ rows tall +- **Markdown**: Flexible, typically 6-12 columns + +### Data Sources +- **Test queries first** - Use EdgeDelta UI to validate queries +- **Use semantic names** - Visual IDs: A, B, C (not random) +- **Optimize queries** - Specific filters, appropriate aggregations +- **Consider cardinality** - Group by limited dimensions + +### Templates +- **Version control** - Store templates in git +- **Parameterize** - Use consistent patterns for easy updates +- **Document** - Add comments explaining complex widgets +- **Test thoroughly** - Create in test org before production + +## Troubleshooting Guide + +### Authentication Issues + +**Problem**: "authentication failed" or "401 Unauthorized" +**Solution**: Check your environment variables are set: +```bash +echo $ED_API_TOKEN +echo $ED_ORG_ID +``` +If empty, set them and restart Claude Code: +```bash +export ED_API_TOKEN="your-token" +export ED_ORG_ID="your-org-id" +``` + +**Problem**: "403 Forbidden" +**Solution**: Your API token may lack required permissions. Create a new token with dashboard read/write access at https://docs.edgedelta.com/api-tokens/ + +**Problem**: Docker not running +**Solution**: Start Docker Desktop or the Docker daemon before starting Claude Code. + +### Validation Errors + +**Problem**: "Dashboard MUST have a root widget" +**Solution**: Add root widget as first widget in array (see schema above) + +**Problem**: "Widget #N is missing 'position' field" +**Solution**: Add position to widget (see schema above) + +**Problem**: "Widget extends beyond grid bounds" +**Solution**: Adjust column/columnSpan to fit in 12 columns + +**Problem**: "Unknown widget type: X" +**Solution**: Use valid widget type (viz, markdown, grid, tabs, variable-control, empty) + +**Problem**: "Unknown visualizer type: X" +**Solution**: Use valid visualizer from list above + +## When to Read Detailed References + +Load reference documentation selectively based on the specific task: + +- **schema-reference.md** - When creating custom widgets or troubleshooting schema errors. Contains complete widget/visualizer/dataSource type definitions. +- **validation-guide.md** - When validation fails or pre-checking complex templates. Contains detailed validation rules and edge cases. +- **troubleshooting.md** - When encountering authentication, API, or MCP errors. Contains comprehensive error resolution steps. +- **create-from-scratch.md** - When building a completely new dashboard with no starting template. Contains step-by-step creation workflow. +- **batch-operations.md** - When migrating or managing multiple dashboards. Contains bulk operation strategies and migration patterns. +- **export-and-modify.md** - When customizing existing dashboards. Contains best practices for export-modify-update workflow. + +**Reference location**: `${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/references/` + +## Quick Reference + +### MCP Tools + +``` +# List all dashboards +get_all_dashboards [include_definitions: true/false] + +# Get a specific dashboard +get_dashboard(dashboard_id: "") + +# Builder workflow +get_dashboard_schema [category: timeseries|scalar|aggregates|other|layout] +create_widget(widget_type: "", data_source_type: "", ...) +assemble_dashboard(name: "", widgets: [...]) + +# Direct create / update / delete +create_dashboard(dashboard_definition: "") +update_dashboard(dashboard_id: "", dashboard_definition: "") +delete_dashboard(dashboard_id: "") +``` + +### Asset Templates +Dashboard starter templates are available in: +`${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/` +- `quickstart-dashboard.yaml` — Minimal single-widget example +- `system-metrics.yaml` — Multi-panel metrics dashboard +- `logs-analysis.yaml` — Log-focused dashboard + diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/logs-analysis.yaml b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/logs-analysis.yaml new file mode 100644 index 0000000..0811c41 --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/logs-analysis.yaml @@ -0,0 +1,151 @@ +# Log Analysis Dashboard - v4 EdgeDelta Dashboard +# Comprehensive log monitoring with error tracking and volume analysis + +dashboard_name: "Log Analysis Dashboard" +description: "Log monitoring, error tracking, and volume analysis by service and severity" +tags: + - logs + - errors + - observability + +definition: + version: 4 + + timeFilters: + lookback: "24h" + + widgets: + # ROOT WIDGET - REQUIRED! Must be first widget + - id: "root" + type: "grid" + grid: "72px 72px 72px 72px 72px 72px 72px 72px 72px 72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" + # 12 rows × 12 columns + + # WIDGET 1: Log Volume by Severity (stacked area, left 8 cols) + - id: 1 + type: "viz" + resultType: "timeseries" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 8 + row: 1 + rowSpan: 4 + displayOptions: + title: "Log Volume by Severity" + visualizer: + type: "area" + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "*" + + # WIDGET 2: Error Count (big number, right 4 cols) + - id: 2 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: + column: 9 + columnSpan: 4 + row: 1 + rowSpan: 4 + displayOptions: + title: "Error Count (1h)" + thresholds: + - value: 0 + color: "var(--extended-green-500)" + - value: 100 + color: "var(--extended-gold-500)" + - value: 1000 + color: "var(--extended-scarlet-500)" + visualizer: + type: "bignumber" + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "level:ERROR" + timeFiltersOffset: "-23h" # 1h window ending at dashboard lookback + + # WIDGET 3: Top Services by Log Volume (column chart, left 6 cols) + - id: 3 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 6 + row: 5 + rowSpan: 4 + displayOptions: + title: "Top Services by Log Volume" + visualizer: + type: "column" + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "*" + + # WIDGET 4: Recent Errors (raw table, right 6 cols) + - id: 4 + type: "viz" + resultType: "raw" + position: + type: "grid" + targetId: "root" + area: + column: 7 + columnSpan: 6 + row: 5 + rowSpan: 4 + displayOptions: + title: "Recent Error Messages" + visualizer: + type: "raw-table" + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "level:ERROR" + + # WIDGET 5: Full-width log stream (raw table) + - id: 5 + type: "viz" + resultType: "raw" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 12 + row: 9 + rowSpan: 4 + displayOptions: + title: "Log Stream" + visualizer: + type: "raw-table" + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "*" + +# Prerequisites: +# - EdgeDelta agent collecting application logs +# - Logs include severity/level field (DEBUG, INFO, WARN, ERROR, FATAL) +# - Logs tagged with service.name +# - Structured logging with OpenTelemetry semantic conventions diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml new file mode 100644 index 0000000..8ea4cbb --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml @@ -0,0 +1,106 @@ +# Quickstart Dashboard - Minimal Working Example +# This is the simplest valid v4 EdgeDelta dashboard +# Use this as a template for creating new dashboards + +dashboard_name: "Quickstart Dashboard" +description: "Minimal working example of a v4 EdgeDelta dashboard" +tags: + - quickstart + - example + +definition: + version: 4 + + timeFilters: + lookback: "1h" # Options: 15m, 30m, 1h, 3h, 6h, 12h, 24h, 7d, 30d + + widgets: + # ROOT WIDGET - REQUIRED! Must be first widget + - id: "root" + type: "grid" + grid: "72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" + # Grid format: "rows / columns" + # Standard: 12 columns, 72px per row + + # WIDGET 1: Simple BigNumber showing total log count + - id: 1 + type: "viz" + resultType: "aggregate" + + # Position on grid (REQUIRED for all non-root widgets) + position: + type: "grid" + targetId: "root" # Parent grid + area: + column: 1 # Start at column 1 (1-12) + columnSpan: 6 # Width: 6 columns (half width) + row: 1 # Start at row 1 + rowSpan: 2 # Height: 2 rows + + # Display settings + displayOptions: + title: "Total Logs" + + # Visualizer type + visualizer: + type: "bignumber" + + # Data query + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "*" # All logs + + # WIDGET 2: Line chart showing log volume over time + - id: 2 + type: "viz" + resultType: "timeseries" + + position: + type: "grid" + targetId: "root" + area: + column: 7 # Start at column 7 (right side) + columnSpan: 6 # Width: 6 columns (half width) + row: 1 # Same row as widget 1 + rowSpan: 2 # Height: 2 rows + + displayOptions: + title: "Log Volume Over Time" + + visualizer: + type: "line" + + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "*" + +# Contract: What this dashboard needs to work +# Not required by schema, but helpful for documentation +contract: + required_data_sources: + - "logs" + + prerequisites: | + ## Prerequisites + + This quickstart dashboard requires: + 1. EdgeDelta agent collecting logs + 2. Logs being sent to EdgeDelta backend + + ### Verification + + Run this command to verify logs are available: + ``` + # In EdgeDelta UI, go to Logs and verify you see data + ``` + + ### Expected Data + + - Any logs from any source + - No specific fields required diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/system-metrics.yaml b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/system-metrics.yaml new file mode 100644 index 0000000..2590396 --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/system-metrics.yaml @@ -0,0 +1,108 @@ +# System Metrics Dashboard - v4 EdgeDelta Dashboard +# Monitors CPU, memory, and disk usage across hosts + +dashboard_name: "System Metrics" +description: "CPU, memory, and disk utilization across hosts" +tags: + - metrics + - system + - monitoring + +definition: + version: 4 + + timeFilters: + lookback: "1h" + + widgets: + # ROOT WIDGET - REQUIRED! Must be first widget + - id: "root" + type: "grid" + grid: "72px 72px 72px 72px 72px 72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" + # 8 rows × 12 columns + + # WIDGET 1: CPU Usage (line chart, left half) + - id: 1 + type: "viz" + resultType: "timeseries" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 6 + row: 1 + rowSpan: 4 + displayOptions: + title: "CPU Usage (%)" + yAxis: + label: "CPU %" + min: 0 + max: 100 + visualizer: + type: "line" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:system.cpu.utilization{*}" + + # WIDGET 2: Memory Usage (line chart, right half) + - id: 2 + type: "viz" + resultType: "timeseries" + position: + type: "grid" + targetId: "root" + area: + column: 7 + columnSpan: 6 + row: 1 + rowSpan: 4 + displayOptions: + title: "Memory Usage (%)" + yAxis: + label: "Memory %" + min: 0 + max: 100 + visualizer: + type: "line" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:system.memory.utilization{*}" + + # WIDGET 3: Disk Usage (full-width bar chart) + - id: 3 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 12 + row: 5 + rowSpan: 4 + displayOptions: + title: "Disk Usage (%)" + yAxis: + label: "Disk %" + min: 0 + max: 100 + visualizer: + type: "column" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:system.disk.utilization{*}" + +# Prerequisites: +# - EdgeDelta agent with system metrics collection enabled +# - Metrics: system.cpu.utilization, system.memory.utilization, system.disk.utilization +# - Using OpenTelemetry semantic conventions for system metrics diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/batch-operations.md b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/batch-operations.md new file mode 100644 index 0000000..73401a6 --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/batch-operations.md @@ -0,0 +1,305 @@ +# Batch Operations Guide + +Guide to managing multiple dashboards efficiently using MCP tools. + +## Use Cases + +Batch operations are useful for: +- **Backup/Recovery**: Export all dashboards for disaster recovery +- **Migration**: Move dashboards between organizations or environments +- **Multi-Tenant**: Deploy standard dashboard sets to multiple organizations +- **Bulk Updates**: Apply changes to multiple dashboards simultaneously +- **Onboarding**: Provision standard dashboards for new teams/services + +## Batch Export: Backup All Dashboards + +### Scenario +Export all dashboards from an organization for backup or migration. + +### Workflow + +1. List all dashboards: + ``` + get_all_dashboards() + ``` + Returns a list of all dashboard IDs and names. + +2. For each dashboard ID, retrieve the full definition: + ``` + get_dashboard(id="dash_abc123") + get_dashboard(id="dash_def456") + get_dashboard(id="dash_ghi789") + ``` + +3. Save each definition as a YAML file in a `dashboard-backups/` directory. + +4. Commit to version control: + ```bash + git add dashboard-backups/ + git commit -m "Dashboard backup $(date +%Y-%m-%d)" + ``` + +### Automated Approach + +For large organizations, ask Claude to iterate through all dashboards: + +> "Export all my EdgeDelta dashboards and save them as YAML files in a dashboard-backups directory, one file per dashboard named by dashboard ID." + +Claude will use `get_all_dashboards` then `get_dashboard` for each, then write the files. + +## Batch Create: Deploy Standard Dashboards + +### Scenario +Deploy a standard set of dashboards to a new organization or service. + +### Prepare Templates + +Create a directory of YAML templates: + +``` +dashboard-templates/ +├── system-metrics.yaml +├── application-performance.yaml +├── error-tracking.yaml +└── user-analytics.yaml +``` + +### Workflow + +1. For each YAML file, read it and create the dashboard: + ``` + create_dashboard(definition=) + create_dashboard(definition=) + ... + ``` + +2. Or use the builder workflow for new dashboards: + ``` + assemble_dashboard(name="System Metrics", widgets=[...]) + assemble_dashboard(name="Application Performance", widgets=[...]) + ``` + +### Multi-Organization Deployment + +To deploy the same dashboards to multiple organizations, set `ED_ORG_ID` to each target org and repeat the create workflow. Since `ED_ORG_ID` is an environment variable, you can run Claude Code sessions with different org IDs set. + +### Service-Specific Dashboard Sets + +Organize templates by service: + +``` +dashboard-templates/ +├── web-service/ +│ ├── web-overview.yaml +│ ├── web-errors.yaml +│ └── web-performance.yaml +├── api-service/ +│ ├── api-overview.yaml +│ ├── api-latency.yaml +│ └── api-errors.yaml +└── database-service/ + ├── db-overview.yaml + ├── db-queries.yaml + └── db-connections.yaml +``` + +Create a specific service set by passing those files to `create_dashboard`. + +## Batch Update: Apply Changes to Multiple Dashboards + +### Scenario +Update multiple dashboards with a common change (e.g., time range, new widget). + +### Workflow + +1. Export all dashboards using `get_all_dashboards` + `get_dashboard`. + +2. Apply the change to the definitions (e.g., update `lookback`, add a widget, change a query). + +3. For each modified dashboard, update it: + ``` + update_dashboard(id="dash_abc123", definition=) + update_dashboard(id="dash_def456", definition=) + ... + ``` + +### Example: Change Time Range Across All Dashboards + +Ask Claude: + +> "Change the default time range to 3h on all my dashboards." + +Claude will: +1. List all dashboards +2. Retrieve each definition +3. Update `timeFilters.lookback` from `"1h"` to `"3h"` in each +4. Call `update_dashboard` for each + +### Example: Add Standard Widget to All Dashboards + +Ask Claude: + +> "Add an Agent Health bignumber widget in the top-right corner of all my dashboards." + +Claude will retrieve each dashboard definition, add the widget, adjust positioning, and call `update_dashboard` for each. + +Example widget to add: +```yaml +- id: 999 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: + column: 10 + columnSpan: 3 + row: 1 + rowSpan: 2 + displayOptions: + title: "Agent Health" + visualizer: + type: "bignumber" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "count:edgedelta.agent.healthy{*}" +``` + +## Batch Delete (with Caution!) + +### Scenario +Clean up test/temporary dashboards in bulk. + +**WARNING**: This is destructive! Always: +1. Export backups first using `get_all_dashboards` + `get_dashboard` +2. Double-check the list of IDs to delete +3. Review before proceeding + +### Workflow + +1. List all dashboards and identify the ones to delete: + ``` + get_all_dashboards() + ``` + +2. Confirm the exact IDs to be deleted with the user. + +3. Delete each one: + ``` + delete_dashboard(id="dash_test001") + delete_dashboard(id="dash_test002") + ``` + +Always confirm with the user before batch deletion. The `delete_dashboard` operation is permanent. + +## Real-World Workflows + +### Workflow 1: Multi-Environment Promotion + +Promote dashboards from staging to production: + +1. Export all dashboards from staging (set `ED_ORG_ID` to staging org): + ``` + get_all_dashboards() + get_dashboard(id="") + ``` + +2. Review and optionally modify definitions for production (update tags, environment labels, queries). + +3. Set `ED_ORG_ID` to production org and restart Claude Code. + +4. Create dashboards in production: + ``` + create_dashboard(definition=) + ``` + +### Workflow 2: Disaster Recovery + +Restore dashboards from saved YAML files: + +1. Load the YAML files from your backup directory. +2. For each file: + ``` + create_dashboard(definition=) + ``` + +### Workflow 3: Team Onboarding + +Provision standard dashboards for a new team: + +1. Load your team-standard YAML templates. +2. Create each dashboard, optionally updating the `dashboard_name` to include the team prefix: + ``` + create_dashboard(definition=) + ``` + +### Workflow 4: Dashboard Migration + +Migrate dashboards to a new organization: + +1. Export from the source org. +2. Update `ED_ORG_ID` to the target org. +3. Create each dashboard in the target org. + +## Best Practices + +### 1. Always Backup Before Batch Operations + +Before bulk updates or deletes, export all current dashboards first. Save them as YAML files in a versioned directory. + +### 2. Use Version Control + +Store dashboard YAML definitions in git: +```bash +git add dashboard-templates/ +git commit -m "Update dashboard templates for Q4" +``` + +Deploy from a known commit state for reproducibility. + +### 3. Test in Non-Production First + +Deploy to a staging org first, verify in the EdgeDelta UI, then promote to production. + +### 4. Use Descriptive Naming + +```yaml +# Include environment/purpose in dashboard name +dashboard_name: "[Production] System Metrics - Web Service" +tags: + - production + - web-service + - system +``` + +### 5. Document Batch Operations + +Keep a deployment log: +```bash +echo "$(date): Deployed dashboards to $ED_ORG_ID" >> deployment-log.txt +git commit -m "Deploy dashboards $(date +%Y-%m-%d)" +``` + +### 6. Handle Failures Gracefully + +If a batch create partially fails: +1. Note which IDs succeeded from the output +2. Fix the failing definitions using the error messages as guidance +3. Retry only the failed ones + +## Troubleshooting + +### Some Dashboards Fail to Create + +Check the validation error returned by `create_dashboard`. Use `get_dashboard_schema` to verify valid field values, or use the `create_widget` → `assemble_dashboard` builder workflow to catch errors per-widget. + +### Rate Limiting + +If you hit rate limits (`429 Too Many Requests`), wait a few seconds between operations. Ask Claude to pause between calls if you're doing a large batch. + +### Duplicate Names + +Before creating, use `get_all_dashboards` to check existing dashboard names. Avoid creating duplicates by checking the returned list. diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/create-from-scratch.md b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/create-from-scratch.md new file mode 100644 index 0000000..77765df --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/create-from-scratch.md @@ -0,0 +1,434 @@ +# Creating a Dashboard from Scratch + +Step-by-step guide to creating a new EdgeDelta dashboard using MCP tools. + +## Scenario + +You want to create a new dashboard to monitor application performance with: +- CPU usage metric (big number) +- Memory usage metric (big number) +- Request rate over time (line chart) +- Error rate over time (line chart) + +## Prerequisites + +- Docker installed and running +- `ED_API_TOKEN` and `ED_ORG_ID` set as environment variables +- Application metrics being collected in EdgeDelta + +## Step 1: Verify Authentication + +Check that environment variables are set in your shell: +```bash +echo $ED_API_TOKEN # Should print your token +echo $ED_ORG_ID # Should print your org ID +``` + +Then verify the MCP connection works: +``` +Use get_all_dashboards tool to list existing dashboards +``` + +If this returns an error, see `troubleshooting.md` for authentication issues. + +## Step 2: Design the Dashboard Layout + +Sketch your layout before building: +``` +[CPU ][MEM ][ ][ ] ← Rows 1-2 (cols 1-3, 4-6) +[ Request Rate ] ← Rows 3-5 (cols 1-12) +[ Error Rate ] ← Rows 6-8 (cols 1-12) +``` + +**Grid math**: `column + columnSpan ≤ 13` (12-column layout) + +## Step 3: Verify Queries in EdgeDelta UI (Recommended) + +Before building the dashboard, verify your queries return data: + +1. Go to EdgeDelta UI: https://app.edgedelta.com +2. Navigate to Metrics explorer +3. Test each query: + - `avg:system.cpu.utilization{service:myapp}` + - `avg:system.memory.utilization{service:myapp}` + - `sum:http.server.request.count{service:myapp}` + - `sum:http.server.request.count{service:myapp,status:5xx}` + +If queries return no data: +- Verify metric names are correct +- Check service tag matches your application +- Adjust time range if needed +- Ensure metrics are being collected + +## Step 4: Build Widgets with create_widget + +Use `create_widget` to validate each widget before assembly: + +**Widget 1: CPU Usage (bignumber)** +``` +create_widget( + type="viz", + visualizerType="bignumber", + resultType="aggregate", + title="CPU Usage", + dataSourceType="metric", + query="avg:system.cpu.utilization{service:myapp}", + position={"column": 1, "columnSpan": 3, "row": 1, "rowSpan": 2} +) +``` + +**Widget 2: Memory Usage (bignumber)** +``` +create_widget( + type="viz", + visualizerType="bignumber", + resultType="aggregate", + title="Memory Usage", + dataSourceType="metric", + query="avg:system.memory.utilization{service:myapp}", + position={"column": 4, "columnSpan": 3, "row": 1, "rowSpan": 2} +) +``` + +**Widget 3: Request Rate (line chart)** +``` +create_widget( + type="viz", + visualizerType="line", + resultType="timeseries", + title="Request Rate (req/s)", + dataSourceType="metric", + query="sum:http.server.request.count{service:myapp}", + position={"column": 1, "columnSpan": 12, "row": 3, "rowSpan": 3} +) +``` + +**Widget 4: Error Rate (line chart)** +``` +create_widget( + type="viz", + visualizerType="line", + resultType="timeseries", + title="Error Rate (errors/s)", + dataSourceType="metric", + query="sum:http.server.request.count{service:myapp,status:5xx}", + position={"column": 1, "columnSpan": 12, "row": 6, "rowSpan": 3} +) +``` + +Each call returns a validated widget config. Collect all four. + +## Step 5: Assemble and Create the Dashboard + +``` +assemble_dashboard( + name="Application Performance", + description="Monitor application CPU, memory, requests, and errors", + tags=["application", "performance", "monitoring"], + timeFilters={"lookback": "1h"}, + widgets=[, , , ] +) +``` + +The tool validates the full layout and creates the dashboard in one call. + +Expected result: +``` +Dashboard created successfully +Dashboard ID: dash_abc123def456 +Name: Application Performance +URL: https://app.edgedelta.com/orgs/your-org-id/dashboards/dash_abc123def456 +``` + +## Step 6: Verify in EdgeDelta UI + +1. Click the URL from the result, or: +2. Go to https://app.edgedelta.com +3. Navigate to Dashboards +4. Find "Application Performance" +5. Verify all 4 widgets display correctly + +## Step 7: Iterate and Improve + +If something doesn't look right: + +1. Retrieve the current state: + ``` + get_dashboard(id="dash_abc123def456") + ``` + +2. Modify the definition (adjust widget configs, positions, queries) + +3. Update the dashboard: + ``` + update_dashboard(id="dash_abc123def456", definition=) + ``` + +## Reference: Full Dashboard JSON Structure + +For direct `create_dashboard` usage (bypassing the builder workflow): + +```yaml +dashboard_name: "Application Performance" +description: "Monitor application CPU, memory, requests, and errors" +tags: + - application + - performance + - monitoring + +definition: + version: 4 + + timeFilters: + lookback: "1h" + + widgets: + # ROOT WIDGET - Always required! + - id: "root" + type: "grid" + grid: "72px 72px 72px 72px 72px 72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" + # 8 rows × 12 columns + + # WIDGET 1: CPU Usage (top-left) + - id: 1 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 3 + row: 1 + rowSpan: 2 + displayOptions: + title: "CPU Usage" + visualizer: + type: "bignumber" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:system.cpu.utilization{service:myapp}" + + # WIDGET 2: Memory Usage + - id: 2 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: + column: 4 + columnSpan: 3 + row: 1 + rowSpan: 2 + displayOptions: + title: "Memory Usage" + visualizer: + type: "bignumber" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:system.memory.utilization{service:myapp}" + + # WIDGET 3: Request Rate (full width) + - id: 3 + type: "viz" + resultType: "timeseries" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 12 + row: 3 + rowSpan: 3 + displayOptions: + title: "Request Rate (req/s)" + yAxis: + label: "Requests/sec" + min: 0 + visualizer: + type: "line" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "sum:http.server.request.count{service:myapp}" + + # WIDGET 4: Error Rate (full width) + - id: 4 + type: "viz" + resultType: "timeseries" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 12 + row: 6 + rowSpan: 3 + displayOptions: + title: "Error Rate (errors/s)" + yAxis: + label: "Errors/sec" + min: 0 + visualizer: + type: "line" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "sum:http.server.request.count{service:myapp,status:5xx}" +``` + +## Common Adjustments + +### Adjust Grid Layout + +If widgets are too small/large: + +```yaml +# Make CPU/Memory widgets taller +rowSpan: 3 # Instead of 2 + +# Make them wider +columnSpan: 4 # Instead of 3 + +# Adjust subsequent widgets' row positions accordingly +``` + +### Change Time Range + +```yaml +# Dashboard-level +timeFilters: + lookback: "3h" # Instead of "1h" + +# Per-widget offset +dataSource: + type: "metric" + params: {...} + timeFiltersOffset: "-1d" # Compare to yesterday +``` + +### Add Colors/Thresholds + +```yaml +displayOptions: + title: "CPU Usage" + thresholds: + - value: 0 + color: "#00ff00" # Green below 75% + - value: 75 + color: "#ffaa00" # Orange 75-90% + - value: 90 + color: "#ff0000" # Red above 90% +``` + +### Add Formula Widget + +Calculate error rate percentage: + +```yaml +- id: 5 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: + column: 7 + columnSpan: 3 + row: 1 + rowSpan: 2 + displayOptions: + title: "Error Rate %" + visualizer: + type: "bignumber" + visuals: + - id: "W" # Formulas use W-Z + dataSource: + type: "formula" + params: + formula: "(A / B) * 100" # (errors / total requests) * 100 +``` + +## Tips + +### Tip 1: Start Simple +Build with 1-2 widgets first, verify they work, then add more. + +### Tip 2: Use Consistent Sizing +- Big numbers: 2-3 columns × 2 rows +- Small charts: 6 columns × 3 rows +- Large charts: 12 columns × 3-4 rows + +### Tip 3: Plan Grid Layout +Sketch your layout first: +``` +[CPU][MEM][---][---] ← Row 1-2 +[ Request Rate ] ← Row 3-5 +[ Error Rate ] ← Row 6-8 +``` + +### Tip 4: Tag for Organization +```yaml +tags: + - application # What it monitors + - performance # Category + - team-platform # Ownership + - prod # Environment +``` + +### Tip 5: Use the Builder Workflow +`get_dashboard_schema` → `create_widget` (per widget) → `assemble_dashboard` catches errors early, before any API calls are made. + +## Next Steps + +- **Export and Modify**: Use `get_dashboard` on an existing dashboard and modify the result +- **Batch Operations**: See `batch-operations.md` for creating multiple dashboards +- **Schema Reference**: See `schema-reference.md` for all widget and visualizer types + +## Troubleshooting + +### Dashboard Created but Shows "No Data" + +1. Check time range (try longer: `24h` instead of `1h`) +2. Verify queries in Metrics explorer +3. Check service tag matches your application +4. Wait 5-10 minutes for data to populate + +### Widgets Overlapping + +Check grid positions don't overlap: +```yaml +# Widget 1: rows 1-2 +row: 1, rowSpan: 2 # Uses rows 1, 2 + +# Widget 2: rows 3-5 (not 2-4!) +row: 3, rowSpan: 3 # Uses rows 3, 4, 5 +``` + +### Layout Looks Wrong + +Increase grid rows in root widget: +```yaml +- id: "root" + type: "grid" + grid: "72px 72px 72px 72px 72px 72px 72px 72px / 1fr..." + # 8 rows instead of 5 +``` + +## Template Dashboards + +For ready-to-use starting points: +- Quickstart: `${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml` +- System Metrics: `${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/system-metrics.yaml` +- Logs Analysis: `${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/logs-analysis.yaml` diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/export-and-modify.md b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/export-and-modify.md new file mode 100644 index 0000000..d8dbff6 --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/export-and-modify.md @@ -0,0 +1,394 @@ +# Export and Modify Existing Dashboard + +Guide to retrieving an existing dashboard, modifying it, and updating it via MCP. + +## Scenario + +You have an existing dashboard in EdgeDelta UI that you want to: +- Export to YAML for version control +- Modify locally (add new widget, change layout) +- Update back to EdgeDelta +- Keep as a template for creating similar dashboards + +## Prerequisites + +- `ED_API_TOKEN` and `ED_ORG_ID` set as environment variables +- Dashboard ID from EdgeDelta UI + +## Step 1: Find Dashboard ID + +### Option 1: Via MCP Tool +``` +get_all_dashboards() +``` + +Returns a list of all dashboards with their IDs and names: +``` +ID Name Description Tags +dash_abc123... System Metrics CPU, Memory, Disk production, system +dash_def456... Application Logs Error tracking logs, app +``` + +### Option 2: Via EdgeDelta UI +1. Go to https://app.edgedelta.com/dashboards +2. Click on the dashboard +3. Copy ID from URL: `https://app.edgedelta.com/orgs/{org-id}/dashboards/{dashboard-id}` + +## Step 2: Export Dashboard + +``` +get_dashboard(id="dash_abc123") +``` + +This returns the full dashboard definition including all widgets. Save it as `system-metrics.yaml`. + +## Step 3: Review Exported Dashboard + +The exported dashboard will look like: +```yaml +dashboard_name: "System Metrics" +description: "CPU, Memory, Disk monitoring" +tags: + - production + - system + +definition: + version: 4 + timeFilters: + lookback: "1h" + widgets: + - id: "root" + type: "grid" + grid: "..." + - id: 1 + type: "viz" + # ... existing widgets +``` + +## Step 4: Version Control (Recommended) + +```bash +git init # if not already +git add system-metrics.yaml +git commit -m "Export system metrics dashboard" +``` + +## Step 5: Modify Dashboard + +### Example Modification 1: Add New Widget + +Add a disk I/O widget to the exported file: + +```yaml +# Add after existing widgets +- id: 6 # Use next available ID + type: "viz" + resultType: "timeseries" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 12 + row: 7 # Place below existing widgets + rowSpan: 3 + displayOptions: + title: "Disk I/O" + yAxis: + label: "Bytes/sec" + visualizer: + type: "line" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:system.disk.io{*}" +``` + +Also update the root widget `grid` string to include the extra rows. + +### Example Modification 2: Change Layout + +Rearrange existing widgets: + +```yaml +# BEFORE: Two widgets side-by-side +- id: 1 + position: + area: + column: 1 + columnSpan: 6 # Half width + row: 1 + rowSpan: 3 + +- id: 2 + position: + area: + column: 7 + columnSpan: 6 # Half width + row: 1 + rowSpan: 3 + +# AFTER: Stack vertically +- id: 1 + position: + area: + column: 1 + columnSpan: 12 # Full width + row: 1 + rowSpan: 3 + +- id: 2 + position: + area: + column: 1 + columnSpan: 12 # Full width + row: 4 # Below widget 1 + rowSpan: 3 +``` + +### Example Modification 3: Update Queries + +Change metric queries: + +```yaml +# BEFORE +dataSource: + type: "metric" + params: + query: "avg:cpu.percent{*}" + +# AFTER: More specific query +dataSource: + type: "metric" + params: + query: "avg:system.cpu.utilization{service:api,env:prod}" +``` + +### Example Modification 4: Add Dashboard Variables + +```yaml +definition: + version: 4 + + # Add variables section + variables: + - name: "environment" + type: "custom" + options: + - label: "Production" + value: "prod" + - label: "Staging" + value: "staging" + - label: "Development" + value: "dev" + defaultValue: "prod" + + timeFilters: + lookback: "1h" + + widgets: + # ... then use variable in queries + - id: 1 + # ... + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:cpu.percent{env:$environment}" # Use $environment +``` + +## Step 6: Review Changes + +Before updating, review your changes: + +```bash +# If using git +git diff system-metrics.yaml +``` + +Verify: +- Widget positions changed as intended? +- New widgets added correctly? +- Queries updated properly? +- No unintended changes? + +## Step 7: Update Dashboard + +``` +update_dashboard(id="dash_abc123", definition=) +``` + +The MCP server validates the definition before applying the update. + +## Step 8: Verify in EdgeDelta UI + +1. Open the dashboard URL from the update result +2. Check all widgets display correctly +3. Verify new widgets appear +4. Test any new variables +5. Confirm layout matches expectations + +## Step 9: Commit Changes + +```bash +git add system-metrics.yaml +git commit -m "Add disk I/O widget and rearrange layout" +git push +``` + +## Advanced Workflows + +### Workflow 1: Create Template from Dashboard + +Export dashboard and generalize for reuse: + +1. Retrieve: `get_dashboard(id="dash_abc123")` +2. Save as `templates/system-metrics-template.yaml` +3. Edit to generalize: + - Remove specific service tags + - Add variables for customization + - Document prerequisites +4. Use template to create new dashboards: `create_dashboard(definition=)` + +### Workflow 2: Clone Dashboard to Different Org + +1. Export from org 1: `get_dashboard(id="dash_abc123")` +2. Update `ED_ORG_ID` to org 2 in your shell +3. Restart Claude Code to pick up new env var +4. Create in org 2: `create_dashboard(definition=)` + +### Workflow 3: Backup All Dashboards + +1. List all: `get_all_dashboards()` +2. For each ID: `get_dashboard(id="")` +3. Save each as a YAML file +4. Commit to git + +### Workflow 4: Apply Change to Multiple Dashboards + +1. Export all dashboards +2. Modify the definitions (change time range, add widget, etc.) +3. For each: `update_dashboard(id="", definition=)` + +See `batch-operations.md` for more on multi-dashboard workflows. + +## Common Modifications + +### Add Time Comparison + +Compare current vs previous period: + +```yaml +visuals: + - id: "A" # Current period + dataSource: + type: "metric" + params: + query: "avg:cpu.percent{*}" + + - id: "B" # Previous period (1 hour ago) + dataSource: + type: "metric" + params: + query: "avg:cpu.percent{*}" + timeFiltersOffset: "-1h" +``` + +### Add Calculated Metric + +Use formula to calculate percentage: + +```yaml +- id: "W" + dataSource: + type: "formula" + params: + formula: "(A / B) * 100" +``` + +### Change Visualization Type + +```yaml +# BEFORE: Big number +visualizer: + type: "bignumber" +resultType: "aggregate" + +# AFTER: Gauge +visualizer: + type: "gauge" +resultType: "aggregate" +``` + +### Add Thresholds + +```yaml +displayOptions: + title: "CPU Usage" + thresholds: + - value: 0 + color: "#00ff00" + - value: 80 + color: "#ffaa00" + - value: 95 + color: "#ff0000" +``` + +## Troubleshooting + +### Issue: "Dashboard not found" +**Solution**: Verify dashboard ID with `get_all_dashboards`. Confirm `ED_ORG_ID` matches the org that owns the dashboard. + +### Issue: Update succeeds but changes not visible +**Solution**: +- Hard refresh browser (Ctrl+Shift+R) +- Wait 10-30 seconds for cache +- Use `get_dashboard` to verify the update was persisted + +### Issue: "403 Forbidden" on update +**Solution**: Check that your API token has dashboard write permissions. See `troubleshooting.md`. + +### Issue: Validation fails after export +**Solution**: This shouldn't happen with properly exported dashboards. If it does: +1. Check for manual edits that introduced errors +2. Compare with original `get_dashboard` output +3. Validate incremental changes using `create_widget` + +## Best Practices + +1. **Always version control**: Commit before and after modifications +2. **Test in staging**: If available, test updates in non-production org first +3. **Document changes**: Use descriptive commit messages +4. **Back up first**: Call `get_dashboard` and save the original before major modifications +5. **Incremental changes**: Make small changes, test, repeat +6. **Peer review**: Have a teammate review significant changes + +## Example: Complete Modification Workflow + +``` +# 1. Export and save +get_dashboard(id="dash_abc123") +→ save as system-metrics.yaml + +# 2. Version control +git add system-metrics.yaml +git commit -m "Export system metrics dashboard" + +# 3. Modify system-metrics.yaml (add disk I/O widget) + +# 4. Review changes +git diff system-metrics.yaml + +# 5. Update +update_dashboard(id="dash_abc123", definition=) + +# 6. Verify in UI (check dashboard in browser) + +# 7. Commit +git add system-metrics.yaml +git commit -m "Add disk I/O widget to system metrics" +git push +``` diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/schema-reference.md b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/schema-reference.md new file mode 100644 index 0000000..dba4231 --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/schema-reference.md @@ -0,0 +1,548 @@ +# EdgeDelta Dashboard v4 Schema Reference + +Quick reference guide for EdgeDelta v4 dashboard schema structure. + +## Dashboard Structure + +```yaml +dashboard_name: "string" +description: "string (optional)" +tags: ["array", "of", "strings"] +definition: + version: 4 # REQUIRED - must be 4 + timeFilters: + lookback: "1h" # 15m, 30m, 1h, 3h, 6h, 12h, 24h, 7d, 30d + widgets: [...] # Array of widget objects +``` + +## Widget Types (6 Total) + +### 1. Grid Widget (Root - REQUIRED) +Every dashboard MUST have exactly ONE root grid widget: + +```yaml +- id: "root" + type: "grid" + grid: "72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" +``` + +**Grid Format**: `" / "` +- Standard: 12 columns, 72px per row +- Rows: Space-separated row heights (e.g., `72px 72px 72px` = 3 rows) +- Columns: Space-separated column widths (typically 12x `1fr` for equal columns) + +### 2. Viz Widget (Visualizations) +Data visualizations (charts, graphs, metrics): + +```yaml +- id: 1 # Unique integer or string + type: "viz" + resultType: "aggregate" # or "timeseries", "raw", "empty" + position: {...} # REQUIRED + displayOptions: + title: "Widget Title" + visualizer: + type: "bignumber" # See visualizer types below + visuals: [...] # Data sources +``` + +### 3. Markdown Widget +Rich text/HTML content: + +```yaml +- id: 2 + type: "markdown" + position: {...} + displayOptions: + title: "Title" + text: "# Markdown content here" +``` + +### 4. Tabs Widget +Tab navigation container: + +```yaml +- id: 3 + type: "tabs" + position: {...} + tabs: + - label: "Tab 1" + targetId: "widget-id-1" + - label: "Tab 2" + targetId: "widget-id-2" +``` + +### 5. Variable Control Widget +Dashboard variable controls: + +```yaml +- id: 4 + type: "variable-control" + position: {...} + variableName: "my_variable" +``` + +### 6. Empty Widget +Placeholder/spacer: + +```yaml +- id: 5 + type: "empty" + position: {...} +``` + +## Widget Positioning (Grid System) + +**ALL non-root widgets MUST have a position field:** + +```yaml +position: + type: "grid" + targetId: "root" # Parent container (usually "root") + area: + column: 1 # Starting column (1-12, 1-indexed) + columnSpan: 6 # Width in columns (1-12) + row: 1 # Starting row (1+, 1-indexed) + rowSpan: 2 # Height in rows (1+) +``` + +### Grid Rules +- **Column Range**: 1-12 (1-indexed) +- **Column Constraint**: `column + columnSpan ≤ 13` +- **Row Range**: 1+ (1-indexed, no upper limit) +- **No Overlaps**: Widgets should not overlap (not enforced, but recommended) + +### Common Widget Sizes +- **BigNumber/Gauge**: 2-4 columns × 2 rows +- **Small Chart**: 6 columns × 3-4 rows +- **Large Chart**: 12 columns × 4-6 rows +- **Table**: 12 columns × 4+ rows + +## Visualizer Types (24 Total) + +### Scalar Visualizers (resultType: aggregate) +- `bignumber` - Large single metric display +- `gauge` - Gauge chart (0-100 or custom range) + +### Aggregate Visualizers (resultType: aggregate) +- `pie` - Pie chart +- `donut` - Donut chart +- `column` - Vertical bar chart +- `radar` - Radar/spider chart +- `treemap` - Hierarchical treemap +- `sunburst` - Hierarchical sunburst +- `sankey` - Flow diagram +- `bubble` - Bubble chart +- `list` - List view +- `geomap` - Geographic map + +### Timeseries Visualizers (resultType: timeseries) +- `line` - Line chart +- `bar` - Bar chart (time-based) +- `area` - Area chart +- `scatter` - Scatter plot +- `step` - Step chart +- `smooth` - Smoothed line chart + +### Table Visualizers +- `table` - Formatted table with aggregation +- `raw-table` - Raw data table + +### Special Visualizers +- `json` - JSON viewer +- `empty` - Empty placeholder + +## Data Sources + +### Visual Structure +```yaml +visuals: + - id: "A" # A-F for queries, W-Z for formulas + dataSource: + type: "log" # See data source types below + params: {...} + timeFiltersOffset: "1h" # Optional time shift +``` + +### Data Source Types (7 Total) + +#### 1. Metric +Query metric data: + +```yaml +dataSource: + type: "metric" + params: + query: "avg:system.cpu.percent{host:web-*}" +``` + +**Query Format**: `:{}` +- Aggregations: `avg`, `sum`, `min`, `max`, `count`, `p50`, `p90`, `p95`, `p99` +- Example: `avg:cpu.utilization{service:api,env:prod}` + +#### 2. Log +Query log data: + +```yaml +dataSource: + type: "log" + params: + query: "level:ERROR service:api" +``` + +**Query Format**: Filter expressions +- Examples: `*` (all), `level:ERROR`, `service:api AND status:500` + +#### 3. Trace +Query trace/APM data: + +```yaml +dataSource: + type: "trace" + params: + query: "service:api operation:http.request" +``` + +#### 4. Event +Query event data: + +```yaml +dataSource: + type: "event" + params: + query: "event_type:deployment" +``` + +#### 5. Pattern +Log pattern analysis: + +```yaml +dataSource: + type: "pattern" + params: + negative: true + includeOther: true +``` + +#### 6. Formula +Mathematical formulas combining other visuals: + +```yaml +- id: "W" # Formulas use W-Z + dataSource: + type: "formula" + params: + formula: "(A + B) / C * 100" +``` + +**Formula Rules**: +- Can reference other visuals: A, B, C, D, E, F +- Supports: `+`, `-`, `*`, `/`, `()`, numbers +- Example: `(A - B) / A * 100` (percentage change) + +#### 7. Empty +Placeholder: + +```yaml +dataSource: + type: "empty" +``` + +## Result Types + +Match visualizer category with result type: + +| Visualizer Category | Result Type | +|-------------------|-------------| +| Scalar (bignumber, gauge) | `aggregate` | +| Aggregate (pie, donut, column, etc.) | `aggregate` | +| Timeseries (line, bar, area, etc.) | `timeseries` | +| Table (table, raw-table) | `aggregate` or `raw` | +| Special (json, empty) | `raw` or `empty` | + +## Display Options + +Common display options for viz widgets: + +```yaml +displayOptions: + title: "Widget Title" + description: "Optional description" + + # Y-axis configuration (for charts) + yAxis: + label: "Y-axis Label" + min: 0 + max: 100 + + # Legend + legend: + position: "bottom" # top, bottom, left, right, none + alignment: "center" # start, center, end + + # Colors + colorPalette: "default" # or custom palette name + + # Coloring object (preferred for CSS variables) + coloring: + mode: "palette" # or "continuous" + palette: + - "var(--extended-green-500)" + - "var(--extended-orange-500)" + + # Thresholds (for gauge, bignumber) + thresholds: + - value: 0 + color: "#00ff00" + - value: 75 + color: "#ffaa00" + - value: 90 + color: "#ff0000" +``` + +## Color System (CSS Variables) + +EdgeDelta dashboards support CSS custom properties for consistent theming. + +### Extended Colors (weights 200-800) + +| Color | Example | Use Case | +|-------|---------|----------| +| `azure` | `var(--extended-azure-500)` | Info, neutral | +| `rose` | `var(--extended-rose-500)` | Highlights | +| `gold` | `var(--extended-gold-500)` | Warnings, caution | +| `green` | `var(--extended-green-500)` | Success, healthy | +| `orange` | `var(--extended-orange-500)` | Active, attention | +| `violet` | `var(--extended-violet-500)` | Special, unique | +| `scarlet` | `var(--extended-scarlet-500)` | Errors, alerts | +| `gray` | `var(--extended-gray-500)` | Muted, inactive | +| `cyan` | `var(--extended-cyan-500)` | Info, recovery | + +**⚠️ Common Mistake**: `extended-red` is NOT valid. Use `extended-scarlet` instead. + +### Semantic Accent Colors + +```yaml +palette: + - "var(--semantic_accent-blue)" # Information + - "var(--semantic_accent-green)" # Success + - "var(--semantic_accent-yellow)" # Warning + - "var(--semantic_accent-red)" # Error/Critical +``` + +### Coloring Overrides (per-series) + +```yaml +coloringOverrides: + - name: "alert" + coloring: + mode: "palette" + palette: ["var(--extended-scarlet-400)"] + - name: "recovery" + coloring: + mode: "palette" + palette: ["var(--extended-green-400)"] +``` + +## Time Filters + +Dashboard-level time filter: + +```yaml +timeFilters: + lookback: "1h" # How far back to query +``` + +**Valid Lookback Values**: +- Minutes: `15m`, `30m` +- Hours: `1h`, `3h`, `6h`, `12h`, `24h` +- Days: `7d`, `30d` + +**Per-Visual Time Offset**: +```yaml +dataSource: + type: "metric" + params: {...} + timeFiltersOffset: "-1h" # Compare to 1 hour ago +``` + +## Dashboard Variables + +Define variables for dynamic filtering: + +```yaml +definition: + variables: + - name: "environment" + type: "custom" + options: + - label: "Production" + value: "prod" + - label: "Staging" + value: "staging" + defaultValue: "prod" +``` + +**Variable Types**: +- `custom` - Static list of options +- `query` - Dynamic from query results +- `text` - Free-form text input +- `interval` - Time interval selector +- `datasource` - Data source selector +- `constant` - Hidden constant value + +**Using Variables in Queries**: +```yaml +params: + query: "avg:cpu.percent{env:$environment}" +``` + +## Complete Example + +```yaml +dashboard_name: "Complete Example" +description: "Demonstrates all major features" +tags: ["example", "complete"] + +definition: + version: 4 + + timeFilters: + lookback: "1h" + + variables: + - name: "service" + type: "custom" + options: + - {label: "API", value: "api"} + - {label: "Web", value: "web"} + defaultValue: "api" + + widgets: + # Root grid (REQUIRED) + - id: "root" + type: "grid" + grid: "72px 72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" + + # BigNumber metric + - id: 1 + type: "viz" + resultType: "aggregate" + position: + type: "grid" + targetId: "root" + area: {column: 1, columnSpan: 3, row: 1, rowSpan: 2} + displayOptions: + title: "CPU Average" + visualizer: + type: "bignumber" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:cpu.percent{service:$service}" + + # Line chart + - id: 2 + type: "viz" + resultType: "timeseries" + position: + type: "grid" + targetId: "root" + area: {column: 4, columnSpan: 9, row: 1, rowSpan: 4} + displayOptions: + title: "CPU Over Time" + yAxis: + label: "Percent" + min: 0 + max: 100 + visualizer: + type: "line" + visuals: + - id: "A" + dataSource: + type: "metric" + params: + query: "avg:cpu.percent{service:$service}" + + # Table + - id: 3 + type: "viz" + resultType: "raw" + position: + type: "grid" + targetId: "root" + area: {column: 1, columnSpan: 12, row: 5, rowSpan: 4} + displayOptions: + title: "Recent Logs" + visualizer: + type: "raw-table" + visuals: + - id: "A" + dataSource: + type: "log" + params: + query: "service:$service" +``` + +## Validation Checklist + +Before creating/updating a dashboard: + +- [ ] Version is 4 +- [ ] Root widget exists with `id: "root"`, `type: "grid"`, `grid: "..."` +- [ ] All non-root widgets have `position` field +- [ ] All grid positions fit within 12 columns +- [ ] All visualizers are valid types +- [ ] All data source types are valid +- [ ] Result types match visualizer categories +- [ ] Variable references use `$variable_name` syntax +- [ ] Time lookback values are valid +- [ ] Visual IDs are A-F (queries) or W-Z (formulas) + +## Common Patterns + +### Side-by-Side Metrics +```yaml +# Left metric: columns 1-6 +area: {column: 1, columnSpan: 6, row: 1, rowSpan: 2} + +# Right metric: columns 7-12 +area: {column: 7, columnSpan: 6, row: 1, rowSpan: 2} +``` + +### Full-Width Chart +```yaml +area: {column: 1, columnSpan: 12, row: 1, rowSpan: 4} +``` + +### Three-Column Layout +```yaml +# Left: columns 1-4 +area: {column: 1, columnSpan: 4, row: 1, rowSpan: 3} + +# Center: columns 5-8 +area: {column: 5, columnSpan: 4, row: 1, rowSpan: 3} + +# Right: columns 9-12 +area: {column: 9, columnSpan: 4, row: 1, rowSpan: 3} +``` + +### Stacked Rows +```yaml +# Row 1 +area: {column: 1, columnSpan: 12, row: 1, rowSpan: 2} + +# Row 2 +area: {column: 1, columnSpan: 12, row: 3, rowSpan: 3} + +# Row 3 +area: {column: 1, columnSpan: 12, row: 6, rowSpan: 4} +``` + +## Quick Reference URLs + +- EdgeDelta Dashboard UI: `https://app.edgedelta.com/dashboards` +- EdgeDelta Docs: `https://docs.edgedelta.com` +- MCP Server: `https://github.com/edgedelta/edgedelta-mcp-server` diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/troubleshooting.md b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/troubleshooting.md new file mode 100644 index 0000000..8429319 --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/troubleshooting.md @@ -0,0 +1,432 @@ +# EdgeDelta Dashboard Troubleshooting Guide + +Common issues and solutions when working with EdgeDelta dashboards via MCP. + +## Authentication Issues + +### Issue: "Unauthorized" or "Not authenticated" + +**Symptoms**: +``` +Error: 401 Unauthorized +``` + +**Root Cause**: `ED_API_TOKEN` or `ED_ORG_ID` environment variables are missing or incorrect. + +**Solution**: Verify environment variables are set in your shell: +```bash +echo $ED_API_TOKEN # Should print your token +echo $ED_ORG_ID # Should print your org ID +``` + +If missing, set them: +```bash +export ED_API_TOKEN="your-api-token" +export ED_ORG_ID="your-org-id" +``` + +Then restart Claude Code so the Docker container picks up the updated environment. + +### Issue: "403 Forbidden" on Create/Update/Delete + +**Symptoms**: +``` +Error: 403 Forbidden - You don't have permission to perform this action +``` + +**Root Cause**: Your API token does not have write permissions for dashboards. + +**Solution**: +1. Check your token's permission scope in the EdgeDelta UI under Settings → API Tokens +2. Generate a new token with dashboard write permissions +3. Update `ED_API_TOKEN` and restart Claude Code + +**Note**: Dashboard create/update/delete tools require the next MCP server release. If you see 403 errors on write operations, verify that the server version supports dashboard management. + +### Issue: "Organization not found" + +**Symptoms**: +``` +Error: Organization ID 'xyz' not found or you don't have access +``` + +**Solution**: Verify your organization ID: +1. Log into EdgeDelta UI: https://app.edgedelta.com +2. Check URL: `https://app.edgedelta.com/orgs//...` +3. Or go to Settings → Organization → Organization ID +4. Update `ED_ORG_ID` accordingly + +## Docker / MCP Setup Issues + +### Issue: Docker Not Running + +**Symptoms**: +``` +Error: Cannot connect to the Docker daemon +``` + +**Solution**: Start Docker Desktop or the Docker daemon: +```bash +# macOS/Windows: Open Docker Desktop app +# Linux: +sudo systemctl start docker +``` + +### Issue: Image Pull Fails + +**Symptoms**: +``` +Error: Unable to pull image ghcr.io/edgedelta/edgedelta-mcp-server:latest +``` + +**Solution**: +```bash +# Pull manually to see detailed error +docker pull ghcr.io/edgedelta/edgedelta-mcp-server:latest + +# Check Docker Hub authentication if needed +docker login ghcr.io +``` + +### Issue: MCP Server Not Connecting + +**Solution**: +1. Verify MCP config references the correct image +2. Check that `ED_API_TOKEN` and `ED_ORG_ID` are exported in your shell environment +3. Run `/mcp` in Claude Code to check server status + +## Dashboard Validation Errors + +### Issue: "Dashboard MUST have a root widget" + +**Symptoms**: +``` +ERROR: Dashboard MUST have a root widget. Root widget MUST have: +id='root', type='grid', grid=''. +``` + +**Root Cause**: Missing or incorrectly configured root widget. + +**Solution**: Add root widget as first widget in array: +```yaml +widgets: + - id: "root" + type: "grid" + grid: "72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" + + # ... other widgets follow +``` + +### Issue: "Widget #N is missing 'position' field" + +**Symptoms**: +``` +ERROR: Widget #1 is missing 'position' field. All non-root widgets MUST have a position. +``` + +**Solution**: Add position to the widget: +```yaml +- id: 1 + type: "viz" + position: + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 6 + row: 1 + rowSpan: 2 + # ... rest of widget config +``` + +### Issue: "Widget extends beyond grid bounds" + +**Symptoms**: +``` +ERROR: Widget extends beyond grid bounds: column 7 + span 8 = 15 +(exceeds standard 12-column grid). +``` + +**Root Cause**: Widget position exceeds 12-column layout. + +**Solution**: Adjust column or columnSpan: +```yaml +# BAD: 7 + 8 = 15 (exceeds 12) +area: + column: 7 + columnSpan: 8 + +# GOOD: 7 + 6 = 13 (fits in 12 columns) +area: + column: 7 + columnSpan: 6 + +# OR: 1 + 8 = 9 (fits) +area: + column: 1 + columnSpan: 8 +``` + +**Formula**: `column + columnSpan ≤ 13` + +### Issue: "Input should be 4" (Version Error) + +**Symptoms**: +``` +ERROR: Input should be 4 +``` + +**Root Cause**: Wrong dashboard version. + +**Solution**: Set version to 4: +```yaml +definition: + version: 4 # Must be 4, not 3 or other +``` + +### Issue: "Unknown widget type: X" + +**Symptoms**: +``` +ERROR: Unknown widget type: 'chart' +``` + +**Root Cause**: Invalid widget type. + +**Solution**: Use valid widget type: +```yaml +# Valid types: viz, markdown, grid, tabs, variable-control, empty +type: "viz" # NOT "chart" +``` + +### Issue: "Unknown visualizer type: X" + +**Symptoms**: +``` +ERROR: Unknown visualizer type: 'graph' +``` + +**Solution**: Use valid visualizer from the list: +- Single-value: `bignumber`, `gauge` +- Multi-value: `pie`, `donut`, `column`, `radar`, `treemap`, `sunburst`, `sankey`, `bubble`, `list`, `geomap` +- Timeseries: `line`, `bar`, `area`, `scatter`, `step`, `smooth` +- Table: `table`, `raw-table` +- Special: `json`, `empty` + +```yaml +visualizer: + type: "line" # NOT "graph" +``` + +### Issue: "Unknown data source type: X" + +**Symptoms**: +``` +ERROR: Unknown data source type: 'query' +``` + +**Solution**: Use valid data source type: +```yaml +# Valid types: metric, log, trace, event, pattern, formula, empty +dataSource: + type: "log" # NOT "query" +``` + +## MCP Tool Operation Issues + +### Issue: Dashboard Not Found + +**Symptoms**: +``` +Error: Dashboard 'abc-123' not found +``` + +**Solutions**: +1. List all dashboards to find the correct ID: + ``` + Use get_all_dashboards tool + ``` + +2. Verify `ED_ORG_ID` matches the organization that owns the dashboard + +3. Check if the dashboard was deleted + +### Issue: YAML Syntax Error + +**Symptoms**: +``` +Error: yaml.scanner.ScannerError: while scanning... +``` + +**Root Cause**: Invalid YAML syntax in dashboard definition. + +**Solution**: Common YAML issues to check: +- Inconsistent indentation (use 2 spaces, not tabs) +- Missing quotes around special characters (`:`, `{`, `}`, `[`, `]`) +- Incorrect list syntax (each item needs `- ` prefix) + +Use `get_dashboard_schema` to get the canonical field structure, or use the `create_widget` → `assemble_dashboard` builder workflow which handles formatting automatically. + +### Issue: create_widget Returns Error + +**Symptoms**: `create_widget` tool returns a validation error. + +**Solution**: +1. Use `get_dashboard_schema` with the relevant category to see valid field values +2. Check that `visualizerType` and `dataSourceType` are compatible +3. Verify all required fields are present + +### Issue: assemble_dashboard Partially Fails + +**Symptoms**: Some widgets created, but assembly fails. + +**Solution**: +1. Review the error — it will indicate which widget config is invalid +2. Fix the specific widget using `create_widget` again +3. Re-run `assemble_dashboard` with the corrected widget list + +## API/Network Issues + +### Issue: Connection Timeout + +**Symptoms**: +``` +Error: Request timeout after 30 seconds +``` + +**Solutions**: +1. Check network connectivity: + ```bash + curl -I https://api.edgedelta.com + ``` + +2. Check firewall/proxy settings + +3. Try again (transient network issue) + +### Issue: Rate Limiting + +**Symptoms**: +``` +Error: 429 Too Many Requests +``` + +**Solution**: Wait briefly before retrying. The MCP server includes automatic retry with exponential backoff for transient errors. + +## Data Issues + +### Issue: No Data in Dashboard + +**Symptoms**: Dashboard created successfully but shows "No data" in UI. + +**Solutions**: +1. Verify data source queries are correct: + - Test the query in EdgeDelta UI first + - Check metric/log names are exact matches + - Verify the time range includes data + +2. Check data source type matches data: + ```yaml + # For metrics + dataSource: + type: "metric" + params: + query: "avg:system.cpu.percent{*}" + + # For logs + dataSource: + type: "log" + params: + query: "level:ERROR" + ``` + +3. Verify time range: + ```yaml + timeFilters: + lookback: "1h" # Try longer: "24h", "7d" + ``` + +### Issue: Wrong Visualization Type for Data + +**Symptoms**: Dashboard loads but visualization doesn't make sense. + +**Solution**: Match visualizer to data and result type: + +| Data Type | Result Type | Recommended Visualizers | +|-----------|-------------|------------------------| +| Time series metrics | `timeseries` | `line`, `area`, `bar` | +| Single metric value | `aggregate` | `bignumber`, `gauge` | +| Grouped metrics | `aggregate` | `pie`, `donut`, `column` | +| Raw logs | `raw` | `raw-table` | +| Aggregated logs | `aggregate` | `table`, `list` | + +## Debugging Tips + +### Inspect an Existing Dashboard + +Use `get_dashboard` with a known-working dashboard ID to see the exact JSON structure you should replicate: +``` +get_dashboard(id="") +``` + +### Validate Schema First + +Before building a complex dashboard, query the schema to see valid options: +``` +get_dashboard_schema(category="widget-types") +get_dashboard_schema(category="visualizer-types") +get_dashboard_schema(category="data-sources") +``` + +### Use the Builder Workflow + +Rather than writing raw JSON, use `create_widget` for each widget first — it validates each piece individually before you attempt assembly: +``` +1. create_widget(type="viz", visualizerType="line", ...) → widget config +2. create_widget(type="viz", visualizerType="bignumber", ...) → widget config +3. assemble_dashboard(name="My Dashboard", widgets=[...]) +``` + +### Dashboard Updated But Changes Not Visible + +**Solutions**: +1. Hard refresh browser: Ctrl+Shift+R (or Cmd+Shift+R on Mac) +2. Wait 10-30 seconds for cache to clear +3. Use `get_dashboard` to verify the update was persisted +4. Check that `update_dashboard` returned success + +## Getting Help + +### Reference Files +- Schema Reference: `${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/references/schema-reference.md` +- Validation Guide: `${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/references/validation-guide.md` +- MCP Server Source: https://github.com/edgedelta/edgedelta-mcp-server + +### Template Dashboards +Use known-good templates from the assets directory: +``` +${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml +${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/system-metrics.yaml +${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/logs-analysis.yaml +``` + +### EdgeDelta Support +- Documentation: https://docs.edgedelta.com +- Support Portal: Contact your EdgeDelta representative + +## Quick Fixes Summary + +| Issue | Quick Fix | +|-------|----------| +| 401 Unauthorized | Verify `ED_API_TOKEN` is exported in shell | +| 403 Forbidden | Check token has dashboard write permissions | +| Organization not found | Verify `ED_ORG_ID` is correct | +| Docker not running | Start Docker Desktop | +| Image pull fails | `docker pull ghcr.io/edgedelta/edgedelta-mcp-server:latest` | +| Missing root widget | Add root widget as first widget | +| Missing position | Add `position` field to widget | +| Grid bounds exceeded | Adjust column/columnSpan to fit 12 columns | +| Wrong version | Set `version: 4` | +| Invalid type | Use valid widget/visualizer/dataSource type | +| YAML syntax error | Validate YAML, check indentation | +| No data in dashboard | Verify query, time range, data source type | diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/validation-guide.md b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/validation-guide.md new file mode 100644 index 0000000..ebb250e --- /dev/null +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/references/validation-guide.md @@ -0,0 +1,530 @@ +# Dashboard Validation Guide + +Comprehensive guide to EdgeDelta v4 dashboard validation with error patterns and fixes. + +## Validation Overview + +The EdgeDelta MCP server performs validation when creating or updating dashboards. The `create_widget` and `assemble_dashboard` tools also validate incrementally during the builder workflow, catching errors before any API calls are made. + +### Validation Rules + +**Critical Rules (Will Fail)** + +1. **Version must be 4** +2. **Must have at least one widget** +3. **Must have exactly one root widget** (`id='root'`, `type='grid'`) +4. **All non-root widgets must have position** +5. **Grid positions must fit in 12-column layout** +6. **Widget/visualizer/data source types must be valid** + +**Warning Rules (Logged but Allowed)** + +1. Widgets overlapping in grid +2. Empty data source queries +3. Unusual time ranges + +## Error Patterns and Fixes + +### 1. Missing Root Widget + +#### Error Message +``` +ERROR: Dashboard MUST have a root widget. Root widget MUST have: +id='root', type='grid', grid=''. + +Example: {'id': 'root', 'type': 'grid', 'grid': '72px 72px 72px / 1fr 1fr 1fr 1fr'} + +FIX: Add a root grid widget as the first widget in the widgets array. +``` + +#### Root Cause +- No widget with `id='root'` +- Root widget has wrong `type` (not `'grid'`) +- Root widget missing `grid` property + +#### Fix +```yaml +# BEFORE (BROKEN) +definition: + version: 4 + widgets: + - id: 1 + type: "viz" + # ... missing root! + +# AFTER (FIXED) +definition: + version: 4 + widgets: + - id: "root" # ✓ Correct ID + type: "grid" # ✓ Correct type + grid: "72px 72px 72px / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" # ✓ Grid string + + - id: 1 + type: "viz" + # ... rest of widgets +``` + +### 2. Wrong Dashboard Version + +#### Error Message +``` +ERROR: Input should be 4 +``` + +#### Root Cause +Dashboard version is not 4 (e.g., using v3 schema) + +#### Fix +```yaml +# BEFORE (BROKEN) +definition: + version: 3 # ✗ Wrong version + +# AFTER (FIXED) +definition: + version: 4 # ✓ Correct version +``` + +### 3. Missing Position Field + +#### Error Message +``` +ERROR: Widget #1 is missing 'position' field. All non-root widgets MUST have a position. + +FIX: Add position: {'type': 'grid', 'targetId': 'root', 'area': {...}} to widget #1. +``` + +#### Root Cause +Non-root widget doesn't have `position` field + +#### Fix +```yaml +# BEFORE (BROKEN) +- id: 1 + type: "viz" + displayOptions: + title: "My Widget" + visualizer: + type: "bignumber" + # ... missing position! + +# AFTER (FIXED) +- id: 1 + type: "viz" + position: # ✓ Added position + type: "grid" + targetId: "root" + area: + column: 1 + columnSpan: 6 + row: 1 + rowSpan: 2 + displayOptions: + title: "My Widget" + visualizer: + type: "bignumber" +``` + +### 4. Grid Boundary Violation + +#### Error Message +``` +ERROR: Widget extends beyond grid bounds: column 7 + span 8 = 15 +(exceeds standard 12-column grid). + +FIX: Reduce columnSpan or adjust column position to stay within 12 columns. +``` + +#### Root Cause +`column + columnSpan > 13` (widget extends past column 12) + +#### Fix +```yaml +# BEFORE (BROKEN) +position: + type: "grid" + targetId: "root" + area: + column: 7 # ✗ 7 + 8 = 15 > 12 + columnSpan: 8 # ✗ Too wide + +# AFTER (FIXED) - Option 1: Reduce span +position: + type: "grid" + targetId: "root" + area: + column: 7 # ✓ 7 + 6 = 13 ≤ 13 + columnSpan: 6 # ✓ Fits in 12 columns + +# AFTER (FIXED) - Option 2: Move to start +position: + type: "grid" + targetId: "root" + area: + column: 1 # ✓ 1 + 8 = 9 ≤ 13 + columnSpan: 8 # ✓ Fits in 12 columns +``` + +#### Grid Calculation Rule +``` +column + columnSpan ≤ 13 +``` + +Examples: +- column: 1, span: 12 → 1 + 12 = 13 ✓ (full width) +- column: 1, span: 6 → 1 + 6 = 7 ✓ (half width) +- column: 7, span: 6 → 7 + 6 = 13 ✓ (second half) +- column: 7, span: 7 → 7 + 7 = 14 ✗ (exceeds) + +### 5. Invalid Widget Type + +#### Error Message +``` +ERROR: Unknown widget type: 'chart' +``` + +#### Root Cause +Widget type is not one of the 6 valid types + +#### Fix +```yaml +# BEFORE (BROKEN) +- id: 1 + type: "chart" # ✗ Invalid type + +# AFTER (FIXED) +- id: 1 + type: "viz" # ✓ Valid type (for visualizations) + +# Valid widget types: +# - viz (charts, graphs, metrics) +# - markdown (text content) +# - grid (layout container - root only) +# - tabs (tab navigation) +# - variable-control (dashboard variables) +# - empty (placeholder) +``` + +### 6. Invalid Visualizer Type + +#### Error Message +``` +ERROR: Unknown visualizer type: 'graph' +``` + +#### Root Cause +Visualizer type not in the list of 24 valid types + +#### Fix +```yaml +# BEFORE (BROKEN) +visualizer: + type: "graph" # ✗ Invalid + +# AFTER (FIXED) +visualizer: + type: "line" # ✓ Valid for time series + +# Valid visualizer types: +# Single-value: bignumber, gauge +# Multi-value: pie, donut, column, radar, treemap, sunburst, sankey, bubble, list, geomap +# Timeseries: line, bar, area, scatter, step, smooth +# Table: table, raw-table +# Special: json, empty +``` + +### 7. Invalid Data Source Type + +#### Error Message +``` +ERROR: Unknown data source type: 'query' +``` + +#### Root Cause +Data source type not one of 7 valid types + +#### Fix +```yaml +# BEFORE (BROKEN) +dataSource: + type: "query" # ✗ Invalid + +# AFTER (FIXED) - For metrics +dataSource: + type: "metric" # ✓ Valid + params: + query: "avg:cpu.percent{*}" + +# AFTER (FIXED) - For logs +dataSource: + type: "log" # ✓ Valid + params: + query: "level:ERROR" + +# Valid data source types: +# - metric, log, trace, event, pattern, formula, empty +``` + +### 8. Invalid Result Type + +#### Error Message +``` +ERROR: Unknown result type: 'aggregated' +``` + +#### Root Cause +Result type must match visualizer category + +#### Fix +```yaml +# BEFORE (BROKEN) +- id: 1 + type: "viz" + resultType: "aggregated" # ✗ Invalid + +# AFTER (FIXED) +- id: 1 + type: "viz" + resultType: "aggregate" # ✓ Valid (no 'd' at end) + +# Valid result types: +# - timeseries (for line, bar, area, scatter, step, smooth) +# - aggregate (for bignumber, gauge, pie, donut, column, etc.) +# - raw (for raw-table) +# - empty (for empty visualizer) +``` + +### 9. Missing Required Fields + +#### Error Message +``` +ERROR: Field required [type=missing] +``` + +#### Root Cause +Required field is missing from the configuration + +#### Fix +```yaml +# BEFORE (BROKEN) +- id: 1 + type: "viz" + # Missing resultType, visualizer, visuals + +# AFTER (FIXED) +- id: 1 + type: "viz" + resultType: "aggregate" # ✓ Added + position: {...} # ✓ Added + displayOptions: + title: "Title" + visualizer: # ✓ Added + type: "bignumber" + visuals: # ✓ Added + - id: "A" + dataSource: + type: "log" + params: + query: "*" +``` + +### 10. Invalid Visual ID + +#### Error Message +``` +ERROR: Visual ID must be A-F for queries or W-Z for formulas +``` + +#### Root Cause +Visual ID not in allowed range + +#### Fix +```yaml +# BEFORE (BROKEN) +visuals: + - id: "1" # ✗ Invalid (must be letter) + dataSource: + type: "log" + +# AFTER (FIXED) +visuals: + - id: "A" # ✓ Valid (A-F for queries) + dataSource: + type: "log" + +# For formulas +visuals: + - id: "W" # ✓ Valid (W-Z for formulas) + dataSource: + type: "formula" + params: + formula: "A + B" +``` + +## Validation Workflow + +### Option A: Builder Workflow (Recommended) + +Use `get_dashboard_schema` → `create_widget` → `assemble_dashboard`. Each step validates before proceeding: + +1. **`get_dashboard_schema`** — get valid types and field structure +2. **`create_widget`** — validates each widget in isolation +3. **`assemble_dashboard`** — validates the full layout and creates + +Fix errors as `create_widget` reports them, before attempting assembly. + +### Option B: Fix Errors Iteratively + +If working directly with `create_dashboard` or `update_dashboard`: + +1. Read error message carefully +2. Identify the specific widget/field with the issue +3. Apply the fix from this guide +4. Retry + +### Common Scenarios + +**Migrating from v3 to v4:** +1. Update `version: 3` → `version: 4` +2. Add root grid widget if missing +3. Update position format (v3 used different structure) +4. Verify widget types (some changed in v4) + +**Creating from scratch:** +Use the builder workflow. `create_widget` validates one widget at a time, which is easier to debug than a full-dashboard validation error. + +**Modifying an existing dashboard:** +1. Use `get_dashboard` to retrieve the current state +2. Modify the definition +3. Use `update_dashboard` with the corrected definition + +## Validation Error Debugging + +### Identify the Problem Widget + +Error messages include widget index: + +``` +ERROR: Widget #3 is missing 'position' field. +``` + +Find widget #3 (0-indexed, so 4th widget in array): +```yaml +widgets: + - id: "root" # Widget #0 + - id: 1 # Widget #1 + - id: 2 # Widget #2 + - id: 3 # Widget #3 ← This one! + type: "viz" + # ... missing position +``` + +### Check Field Nesting + +Errors might be deeply nested: +``` +ERROR: widgets[3].position.area.column: Field required +``` + +Navigate to that field: +```yaml +widgets: + - # ... root + - # ... widget 1 + - # ... widget 2 + - # Widget 3 + position: + area: + column: ??? # ← Missing this +``` + +## Validation Best Practices + +### 1. Start with Templates + +Use known-good templates from the assets directory: +``` +${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml +${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/system-metrics.yaml +${CLAUDE_PLUGIN_ROOT}/skills/edgedelta-dashboards/assets/logs-analysis.yaml +``` + +### 2. Validate Early, Validate Often + +Use the builder workflow (`create_widget` per widget) rather than writing the full JSON and submitting at once. Errors are easier to fix when isolated to one widget at a time. + +### 3. Use Type-Safe Editors + +VSCode with YAML extension provides: +- Syntax highlighting +- Indentation validation +- Quick error detection + +### 4. Test Queries Separately + +Before adding queries to dashboards, test them in EdgeDelta UI: +- Go to Metrics/Logs explore view +- Test query returns data +- Copy exact query to dashboard + +### 5. Incremental Development + +Build dashboards incrementally: +1. Start with root + 1 widget +2. Validate via `create_widget` and `assemble_dashboard` +3. Use `get_dashboard` to inspect the result +4. Add more widgets using `update_dashboard` +5. Repeat + +### 6. Version Control + +Store dashboard YAML definitions in git: +```bash +git add dashboards/ +git commit -m "Add system metrics dashboard" +``` + +## Quick Validation Checklist + +Before creating/updating a dashboard: + +**Structure** +- [ ] `version: 4` is set +- [ ] Root widget exists with correct format +- [ ] All widgets have unique IDs + +**Positioning** +- [ ] All non-root widgets have `position` +- [ ] All positions have `type`, `targetId`, `area` +- [ ] All `area` have `column`, `columnSpan`, `row`, `rowSpan` +- [ ] All widgets fit in 12-column grid + +**Types** +- [ ] All widget `type` values are valid +- [ ] All `visualizer.type` values are valid +- [ ] All `dataSource.type` values are valid +- [ ] All `resultType` values match visualizers + +**Data** +- [ ] All visual IDs are A-F (queries) or W-Z (formulas) +- [ ] All data source queries are valid +- [ ] Time ranges are valid format + +**Metadata** +- [ ] `dashboard_name` is set +- [ ] Tags are array of strings + +## Common Quick Fixes + +| Error | Quick Fix | +|-------|-----------| +| Missing root widget | Add root as first widget | +| Wrong version | Change to `version: 4` | +| Missing position | Add `position` with `type`, `targetId`, `area` | +| Grid overflow | Reduce `columnSpan` or adjust `column` | +| Invalid widget type | Use: viz, markdown, grid, tabs, variable-control, empty | +| Invalid visualizer | Use valid type from 24 options | +| Invalid data source | Use: metric, log, trace, event, pattern, formula, empty | +| Invalid visual ID | Use A-F for queries, W-Z for formulas | +| Missing required field | Add the required field based on error message | From 4c418121cbe701e70f3cfa2a47432f536e80a88a Mon Sep 17 00:00:00 2001 From: daniel-edgedelta Date: Fri, 6 Mar 2026 16:27:09 -0800 Subject: [PATCH 2/2] fix: apply code review fixes to edgedelta-dashboards plugin - Remove leftover CLI tool trigger phrase from SKILL.md - Add resultType annotations to Table visualizer types in SKILL.md - Align SKILL.md version with plugin.json (both 1.0.0) - Update SKILL.md last_updated to 2026-03-06 - Clarify README availability note with version qualifier - Replace non-schema contract: block in quickstart-dashboard.yaml with plain comments to avoid user confusion --- plugins/edgedelta-dashboards/README.md | 2 +- .../skills/edgedelta-dashboards/SKILL.md | 11 ++++---- .../assets/quickstart-dashboard.yaml | 28 +++---------------- 3 files changed, 10 insertions(+), 31 deletions(-) diff --git a/plugins/edgedelta-dashboards/README.md b/plugins/edgedelta-dashboards/README.md index 146f3bb..dece024 100644 --- a/plugins/edgedelta-dashboards/README.md +++ b/plugins/edgedelta-dashboards/README.md @@ -16,7 +16,7 @@ Create, update, delete, and manage EdgeDelta dashboards directly from Claude Cod 2. **EdgeDelta API token** — [create one here](https://docs.edgedelta.com/api-tokens/) 3. **EdgeDelta organization ID** — [find it here](https://docs.edgedelta.com/my-organization/) -> **Note:** Dashboard management tools (create, update, delete, assemble) require EdgeDelta MCP Server with dashboard support, available in the next MCP server release. The get_all_dashboards and get_dashboard read tools are available today. +> **Note:** Dashboard management tools (create, update, delete, assemble) require EdgeDelta MCP Server v1.1.0 or later with dashboard support. The `get_all_dashboards` and `get_dashboard` read tools are available in all current releases. ## Setup diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/SKILL.md b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/SKILL.md index 8fa4cef..3fef7c1 100644 --- a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/SKILL.md +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/SKILL.md @@ -1,7 +1,7 @@ --- name: edgedelta-dashboards -version: 1.1.0 -last_updated: 2025-10-21 +version: 1.0.0 +last_updated: 2026-03-06 description: Create, update, delete, and manage EdgeDelta dashboards via the EdgeDelta MCP server. Use when users need to build monitoring dashboards, add widgets, visualize metrics or logs, export dashboard configurations, or work with the EdgeDelta dashboard schema. Recognizes phrases like "build a dashboard", "add a widget", "dashboard schema", "visualize my metrics", "export dashboard", "EdgeDelta panel", "create a chart", "update my dashboard". --- @@ -17,7 +17,6 @@ Activate this skill when the user mentions: - EdgeDelta visualization, widgets, or panels - Dashboard validation errors or schema issues - Batch dashboard operations or migrations -- "edgedelta-dashboards" CLI tool - Dashboard authentication or login issues ## Prerequisites and Setup @@ -229,9 +228,9 @@ definition: - `line`, `area`, `bar` - Time series charts - `scatter`, `step`, `smooth` - Specialized time series -**Table**: -- `table` - Formatted table -- `raw-table` - Raw data table +**Table** (resultType: aggregate or raw): +- `table` - Formatted table (resultType: aggregate) +- `raw-table` - Raw data table (resultType: raw) **Special**: - `json` - JSON viewer diff --git a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml index 8ea4cbb..af00ff9 100644 --- a/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml +++ b/plugins/edgedelta-dashboards/skills/edgedelta-dashboards/assets/quickstart-dashboard.yaml @@ -80,27 +80,7 @@ definition: params: query: "*" -# Contract: What this dashboard needs to work -# Not required by schema, but helpful for documentation -contract: - required_data_sources: - - "logs" - - prerequisites: | - ## Prerequisites - - This quickstart dashboard requires: - 1. EdgeDelta agent collecting logs - 2. Logs being sent to EdgeDelta backend - - ### Verification - - Run this command to verify logs are available: - ``` - # In EdgeDelta UI, go to Logs and verify you see data - ``` - - ### Expected Data - - - Any logs from any source - - No specific fields required +# Prerequisites (non-schema documentation — not submitted to the API): +# - EdgeDelta agent collecting logs +# - Logs being sent to EdgeDelta backend +# - No specific log fields required — query "*" matches all logs