CtrlK
BlogDocsLog inGet started
Tessl Logo

kopai/otel-instrumentation

Instrument applications with the OpenTelemetry SDK and prove the telemetry is good by validating it against a local Kopai backend. Use when setting up observability, adding tracing/logging/metrics, deciding what to instrument or which attributes to add, retrofitting OTel into an existing codebase, threading context through call chains, configuring sampling, or when traces/logs/metrics aren't appearing after setup. Also use when users say things like "my traces aren't showing up", "I don't see any data", or "how do I add observability to my app". Do NOT use to investigate existing telemetry for a root cause (use root-cause-analysis), to build dashboards (use create-dashboard), or to instrument LLM and agent calls (use otel-genai-instrumentation).

Quality

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

troubleshoot-missing-spans.mdreferences/

titleimpacttags
Missing SpansHIGHtroubleshoot, spans, orphan

Missing Spans

Some telemetry arrives, but not the spans you expected. Diagnose by symptom.

If nothing arrives, start at troubleshoot-no-data.md instead.

Symptom: every span is a root — the trace is flat

Context isn't propagating. This is the most common failure in the whole skill, and the code runs perfectly the entire time it's happening.

npx @kopai/cli traces search --resource-attr "validation.run_id=$RUN_ID" --json \
  | jq -r '.[] | select((.ParentSpanId // "") == "") | .SpanName' | sort | uniq -c | sort -rn

Every name here that isn't an entry point is a break. Go to context-propagation.md — specifically the framework accessor table, since using the wrong context object compiles cleanly and silently detaches everything downstream.

Symptom: the handler span exists, its children don't

Auto-instrumentation for that library isn't installed or isn't hooked.

npm ls @opentelemetry/auto-instrumentations-node       # Node.js
pip list | grep opentelemetry-instrumentation          # Python
go list -m all | grep otelsql                          # Go — per-library wrappers

Go is the usual culprit: it has no blanket auto-instrumentation, so each library needs its own wrapper (otelhttp, otelsql, otelgorm) applied explicitly. Nothing warns you when one is missing.

Also confirm the instrumented client is the one the code actually calls. Wrapping a *sql.DB you then never use is easy to do and invisible.

Symptom: a route produces no span at all

Middleware ordering. OTel middleware registered after the router — or on a sub-router that some paths bypass — never wraps those handlers.

Register it first and outermost. Then re-drive that specific route and re-check assertion A5.

Symptom: spans appear, but named unknown_service or generic

The resource isn't configured. echo $OTEL_SERVICE_NAME in the shell that launched the app; if it's set there but not in the telemetry, the SDK is being configured programmatically with a resource that overrides the environment.

Symptom: business logic spans missing

Nothing auto-instruments your own functions — that's the point of instrument-spans.md. Decide which operations are interesting and aggregable, then add spans there.

Symptom: spans vanish under load but not in dev

Sampling, or a queue overflow. Check OTEL_TRACES_SAMPLER (sampling.md), then raise OTEL_BSP_MAX_QUEUE_SIZE — the batch processor drops spans silently when its queue is full, which looks exactly like sampling.

Symptom: SDK loaded, still nothing from instrumented libraries

Initialisation ordering. The SDK must start before the libraries it patches are imported. In Node.js this means --import/--require, not a require() at the top of server.mjs — by then the modules are already loaded and unpatchable.

Two more causes with the identical symptom — patching that no-ops without an error:

  • Native-ESM dependencies. "type": "module" doesn't disable patching wholesale: CommonJS dependencies still load through the require hook and patch fine. A dependency published as native ESM bypasses that hook and needs OTel's loader hook registered before the app loads: --experimental-loader=@opentelemetry/instrumentation/hook.mjs. Diagnose per dependency, by its packaging — and if the framework ships a native plugin, prefer it over loader mechanics entirely (Fastify → lang-fastify.md).
  • A deprecated instrumentation package. Deprecation doesn't disable the code — it means unmaintained and superseded, so it silently falls behind the framework versions and loader semantics it once patched. Check the version actually installed — npm ls <pkg> (pnpm list <pkg> / yarn why <pkg>) — then npm view <pkg>@<version> deprecated; a bare npm view <pkg> deprecated reads the latest release, which may differ. npm view works in any project regardless of its package manager — it is a registry read, and npm ships with Node. The message is free text: it usually names the replacement; when it doesn't, check the package's migration notes. Either way, spend the time migrating (after a compatibility check), not debugging the abandoned package. Known case: @opentelemetry/instrumentation-fastify@fastify/otel.

Then

Re-drive (drive-traffic.md) with a fresh $RUN_ID and re-run all of validate-traces.md. Fixing propagation frequently reveals a second break behind the first.

references

_sections.md

architectural-patterns.md

attributes.md

cli-reference.md

context-propagation.md

custom-instrumentation.md

drive-traffic.md

instrument-attributes.md

instrument-errors.md

instrument-spans.md

lang-cpp.md

lang-dotnet.md

lang-erlang.md

lang-fastify.md

lang-go.md

lang-java.md

lang-nextjs.md

lang-nodejs.md

lang-php.md

lang-python.md

lang-ruby.md

lang-rust.md

layered-telemetry.md

nextjs-examples.md

otel-docs.md

sampling.md

setup-backend.md

setup-environment.md

troubleshoot-missing-attrs.md

troubleshoot-missing-spans.md

troubleshoot-no-data.md

troubleshoot-wrong-port.md

validate-logs.md

validate-metrics.md

validate-shutdown.md

validate-traces.md

CHANGELOG.md

SKILL.md

tile.json