Investigate and root-cause production issues from live OpenTelemetry telemetry (traces, logs, metrics) with the Kopai SDK in TypeScript code mode. Use this skill to debug errors and error-rate spikes, investigate latency/slowness and timeouts, trace requests across services, find failing or cascading services, and correlate logs to a trace — including vague symptom reports like 'why is my API slow', 'getting 500 errors', 'service is down', 'requests are timing out', or 'something is failing in prod', even when the user never says 'traces' or 'observability'. This analyzes existing telemetry to find a cause. Do NOT use it to add instrumentation (use otel-instrumentation), to build dashboards or visualizations (use create-dashboard), or to fix non-telemetry problems like failing CI, lint errors, unit tests, or SQL query tuning.
77
97%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Columns, filters, and measures for kq.metrics("<Type>").aggregate() / kq.metrics("<Type>").raw()
(and the client.searchMetrics(...) / client.discoverMetrics() shapes). Run a built query with
client.query(q) (fully typed: returns { data } for aggregate, { data, nextCursor } for raw).
Dashboard tiles render raw rows: when feeding a metric tile via
dataSource:{method:"query"}, build it withkq.metrics("<Type>").raw()(not.aggregate()) — see thecreate-dashboardskill.
const { metrics } = await client.discoverMetrics(); — each entry is
{ name, type, unit, description, attributes, resourceAttributes }. Use it to pick a
metric's exact name and type before querying.
Choose the MetricType as the builder argument: kq.metrics("Gauge")… auto-pins it (type
∈ "Gauge" | "Sum" | "Histogram" | "ExponentialHistogram" | "Summary"). No manual
MetricType filter is needed. Value columns are typed per type, since each type stores its
value in different structural columns.
kq.metrics("Gauge") // auto-pins MetricType: "Gauge"
.aggregate()
.where((f) => f.eq("MetricName", "system.cpu.utilization"));| Type | Value column(s) | Use case |
|---|---|---|
Gauge | Value | Point-in-time: CPU, memory, connections |
Sum | Value | Cumulative counters: request/error counts |
Histogram | Count, Sum, Min, Max, BucketCounts, ExplicitBounds | Latency distributions |
ExponentialHistogram | Count, Sum, Positive/NegativeBucketCounts, … | Distributions |
Summary | Count, Sum, ValueAtQuantiles.* | Pre-computed quantiles |
For Gauge/Sum, aggregate over Value (avg/sum/max). For Histogram, aggregate over
Count/Sum/Max.
MetricName, MetricType, MetricUnit, MetricDescription, TimeUnix,
StartTimeUnix, Value, Count, Sum, Min, Max, BucketCounts, ExplicitBounds,
ScopeName, ScopeVersion. Containers for metric attributes: Attributes
(data-point), ResourceAttributes, ScopeAttributes.
// avg CPU by host over the last hour, bucketed every minute
kq.metrics("Gauge")
.aggregate()
.measure((m) => m.avg("Value", "avg_cpu"))
.where((f) => f.eq("MetricName", "system.cpu.utilization"))
.dimension("host.name")
.timeRelative("1h")
.timeSeries("1m")
.build();Percentiles (p50–p999) are ClickHouse-only; on SQLite use avg/max.
| Filter | Flag | Example |
|---|---|---|
| Type (required) | --type | --type Gauge |
| Name | --name | --name system.cpu.utilization |
| Service | --service | --service payment |
| Attribute | --attr | --attr "host.name=web-1" |
| Aggregate (Gauge/Sum only) | --aggregate | --aggregate sum |
| Group by | --group-by | --group-by host.name (repeatable) |
npx @kopai/cli metrics discover --json
npx @kopai/cli metrics search --type Gauge --name system.cpu.utilization --jsonclient.searchMetrics({ metricType, metricName, serviceName, attributes, aggregate, groupBy, limit })
mirrors these (metricType required; aggregate is Gauge/Sum-only and groupBy requires aggregate; limit caps at 1000).