CtrlK
BlogDocsLog inGet started
Tessl Logo

kopai/root-cause-analysis

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

Quality

97%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

workflow-get-context.mdrules/

titleimpacttags
Step 2: Get Full Trace ContextCRITICALworkflow, trace, context, step2

Step 2: Get Full Trace Context

Impact: CRITICAL

Pull every span of a trace, then inspect fields per row. getTrace returns OtelTracesRow[] — no time window or query builder needed.

Get the trace (code mode)

// get-context.mts — run: npx tsx get-context.mts
import { clientFromConfig } from "@kopai/sdk/node";
const client = clientFromConfig();

const traceId = "<traceId>";
const spans = await client.getTrace(traceId); // OtelTracesRow[] — all spans

// Slowest span = likely bottleneck (Duration is NANOSECONDS: 1ms=1e6, 1s=1e9).
const slowest = [...spans].sort(
  (a, b) => Number(b.Duration) - Number(a.Duration)
)[0];

// Earliest Error in the chain = usually closest to root cause.
const firstError = [...spans]
  .filter((s) => s.StatusCode === "Error") // "Unset" | "Ok" | "Error"
  .sort((a, b) => Number(a.Timestamp) - Number(b.Timestamp))[0];

console.log(JSON.stringify({ slowest, firstError }, null, 2));

"Select specific fields" is just reading row props — no --fields flag. Project what you need:

const view = spans.map((s) => ({
  SpanName: s.SpanName,
  Duration: s.Duration, // nanoseconds
  StatusCode: s.StatusCode, // "Unset" | "Ok" | "Error"
  ParentSpanId: s.ParentSpanId,
}));
console.log(JSON.stringify(view, null, 2));

Analysis Points

FieldWhat to Look For
ParentSpanIdSpan hierarchy / call chain (empty on root span)
DurationSlow spans (bottlenecks) — nanoseconds, find the max
SpanAttributesRequest context, parameters
StatusMessageError details, exception info
StatusCode"Ok" / "Error" (successful spans are usually "Unset")

Two questions drive the read: which span is slowest (max Duration) and where the chain first broke (earliest span with StatusCode === "Error", ordered by Timestamp). Reconstruct hierarchy from ParentSpanId to see which call dragged the latency or threw first.

CLI fallback (one-off lookup)

npx @kopai/cli traces get <traceId> --json
npx @kopai/cli traces get <traceId> --fields SpanName,Duration,StatusCode --json

Reference

See references/trace-filters.md for trace columns and field details.

SKILL.md

tile.json