Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
Most instrumentation is added tool-first: someone installs an agent, a dashboard appears, and nine months later an incident happens and the dashboard cannot answer the question being asked. The fix is to invert the order. Write down the five questions you were actually asked during your last three incidents — 'is it everyone or one customer?', 'did it start when we deployed?', 'is it us or the payment provider?' — and treat each one as a requirement. Every question implies a specific signal with specific attributes. A question you cannot answer from what you emit today is a gap; a signal that answers no question on the list is cost you are paying for nothing.
This is a worked example of the inversion. Keep it in the repo as telemetry-questions.md and revisit it after every incident, because incidents are the only honest source of new questions. Note how narrow each answer is: the point is not to emit more, it is to emit the one attribute that turns a shrug into a bisection.
# telemetry-questions.md — written before any SDK is installed
## Q1. Is it everyone, or one customer?
needs: a tenant identifier on the request span
attribute: tenant.id (low cardinality: ~200 tenants, bounded)
answers by: grouping error rate by tenant.id
today: MISSING -> this is the first thing to add
## Q2. Did it start when we deployed?
needs: the build that served the request
attribute: service.version on the Resource (not per-span)
answers by: overlaying error rate on deploy markers
today: present, but set to "unknown" in staging -> fix the build arg
## Q3. Is it us, or the payment provider?
needs: a span around the outbound call, separate from our handler
signal: a CLIENT span named "POST /v1/charges" with a duration
answers by: comparing self-time vs child-time on the request trace
today: MISSING -> requests library is not instrumented
## Q4. Which query got slow?
needs: db.statement (parameterised, never interpolated) on DB spans
answers by: sorting DB spans by duration inside slow traces
today: present via auto-instrumentation
## Q5. Was the user actually affected, or did the retry save them?
needs: the browser's view, not the server's
signal: a browser span for the click, parented to nothing server-side yet
today: MISSING -> module 10 fixes this
## Signals we emit that answer nothing on this list
- jvm_gc_collection_seconds (no JVM in this service) -> drop
- http_requests_total{path=<full URL with IDs>} -> 1.2M series, drop
python3 main.py