Create observability dashboards from OTEL metrics, logs, and traces using Kopai. Use when building metric visualizations, monitoring views, KPI panels, or when the user wants to see their telemetry data in a dashboard — even if they don't say "dashboard" explicitly. Also use when other skills or workflows need to present telemetry data visually (e.g. after root cause analysis).
100
100%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
npx @kopai/cli metrics discover --json to get real metric names, types, and attributesecho '{"uiTree":<tree>,"metadata":{}}' | npx @kopai/cli dashboards create --name "<name>" --tree-version "0.7.0" --jsonkey, type, children array, parentKey, propsparentKey is ""elementsparentKey must reference an existing elementchildren array must list keys of child elementsdataSourcedataSource.method must match a valid SDK method (e.g. searchMetricsPage, searchLogsPage)dataSource.params must match the method's parameter schemametricType in searchMetricsPage params is required — use the type from metrics discover output (Gauge, Sum, Histogram, etc.)metricName should match an actual metric name from discover outputname — dashboard display name (passed via --name)uiTreeVersion — semver string (passed via --tree-version)uiTree — the component tree object with root and elements (in stdin JSON)unit on MetricTimeSeries and MetricHistogram to the raw OTEL unit from metrics discover (e.g. "By", "s", "ms", "1", "{requests}")unit + data rangeyAxisLabel is an optional override — only set it when the auto-derived label is not descriptive enoughStack with direction: "vertical" as root for simple dashboardsGrid with columns: 2 or columns: 3 for metric gridsCard with descriptive titleMetricStat for KPI overview, MetricTimeSeries for trendsMetricHistogram only for Histogram/ExponentialHistogram metric typesheight: 600 on LogTimeline — smaller values collapse the log content and only show a count badgeheight: 300 on MetricTimeSeries and MetricHistogramaggregate: "sum" to params for a single aggregated value (e.g. total bytes). Do NOT use groupBy with MetricStat (use MetricTable for grouped results)When choosing components, always check the metric's type from metrics discover output. Mismatched types render empty or show "--".
For Histogram metrics: use MetricHistogram for distribution views, or MetricTimeSeries for trends over time (renders mean = Sum/Count). MetricStat is NOT compatible with Histogram.
echo '{"uiTree":{"root":"stack-1","elements":{"stack-1":{"key":"stack-1","type":"Stack","props":{"direction":"vertical","gap":"md","align":null},"children":["card-1"],"parentKey":""},"card-1":{"key":"card-1","type":"Card","props":{"title":"CPU Usage","description":null,"padding":null},"children":["ts-1"],"parentKey":"stack-1"},"ts-1":{"key":"ts-1","type":"MetricTimeSeries","props":{"height":300,"showBrush":null,"yAxisLabel":null,"unit":"1"},"children":[],"parentKey":"card-1","dataSource":{"method":"searchMetricsPage","params":{"metricType":"Gauge","metricName":"system.cpu.utilization"}}}}},"metadata":{}}' | npx @kopai/cli dashboards create --name "CPU Dashboard" --tree-version "0.7.0" --jsonIf metrics discover returns an empty array, telemetry data hasn't reached Kopai yet.
npx @kopai/cli metrics discover --json — if this returns data, Kopai is up and receiving telemetryThe CLI returns a JSON error with a message field describing what's wrong. Common issues:
metricType doesn't match the actual type from metrics discover. Re-run discover and use the exact type valuedashboards schema outputparentKey references a non-existent key. Verify all parent-child relationshipsroot value doesn't match any key in elementsWhen creation fails, read the error message, fix the tree, and retry. Do not guess — always validate against the schema and discover output.
After the dashboard is created, display the URL to the user:
<baseUrl>/?tab=metrics&dashboardId=<id><id> — the id field from the CLI JSON response<baseUrl> — the URL used for the CLI command: the --url flag value, or http://localhost:8000 if omittedCommon pitfalls:
severityNumberMin unless the user explicitly asks for error logs. Many services only emit info-level logs, so filtering to ERROR+ returns empty results. Default to showing all logs.