$npx -y skills add getsentry/sentry-for-ai --skill sentry-instrumentation-guideDecide which Sentry signal to reach for when instrumenting code — error, span, span attribute, log, or metric. Use when adding instrumentation and unsure whether something should be a log vs a span vs a metric, when deciding "what to instrument where", when reviewing instrumentat
| 1 | > [All Skills](../../SKILL_TREE.md) > [Feature Setup](../sentry-feature-setup/SKILL.md) > Instrumentation Guide |
| 2 | |
| 3 | # Sentry Instrumentation Guide: When to Reach for What |
| 4 | |
| 5 | Errors, traces, logs, and metrics are the four kinds of telemetry most apps run on, and they |
| 6 | overlap enough that the choice is rarely obvious. You can stuff context into a span attribute |
| 7 | instead of logging it. You can count log lines instead of emitting a metric. You can add a |
| 8 | duration to a log and call it a span. |
| 9 | |
| 10 | But each signal exists because it answers a **different question** and feeds a **different |
| 11 | workflow** once it lands. Reaching for the wrong one means the data is technically there but |
| 12 | useless for the job you actually have later. This skill is the decision framework: given a value |
| 13 | or an event in front of you, which signal should carry it, and why. |
| 14 | |
| 15 | It decides **what** to emit. For **how** to turn each pillar on for a given stack, hand off to the |
| 16 | `sentry-*-sdk` skills and `sentry-setup-ai-monitoring`. |
| 17 | |
| 18 | ## Invoke This Skill When |
| 19 | |
| 20 | - You're instrumenting a piece of code and unsure whether something should be a log, a span, a |
| 21 | span attribute, or a metric |
| 22 | - You're deciding "what to instrument where" across a service or request handler |
| 23 | - You're reviewing existing instrumentation for gaps (e.g. an error feed that's empty while users |
| 24 | report problems) |
| 25 | - A coding agent needs a consistent rule for choosing between errors, traces, logs, and metrics |
| 26 | |
| 27 | **Important:** The SDK APIs and code samples here are illustrative. Verify exact signatures and |
| 28 | minimum versions against [docs.sentry.io](https://docs.sentry.io) and the relevant `sentry-*-sdk` |
| 29 | skill before implementing. |
| 30 | |
| 31 | ## The Four Signals, One Question Each |
| 32 | |
| 33 | | Signal | The question it answers | Docs | |
| 34 | |--------|-------------------------|------| |
| 35 | | **Errors** | "What just broke?" — a stack trace and exception type, grouped into a deduplicated Issue that gets assigned and tracked to resolution. If your code threw, it's an error. | [Issues](https://docs.sentry.io/product/issues/) | |
| 36 | | **Traces** | "Did the request flow the way it was supposed to?" — a waterfall of timed spans. Mostly auto-instrumented. | [Trace Explorer](https://docs.sentry.io/product/explore/trace-explorer/) | |
| 37 | | **Logs** | "What was true at this point in the code, and why?" — the system's state at one moment as a structured event: config, flags, inputs/outputs, the decision that was made. | [Logs](https://docs.sentry.io/product/explore/logs/) | |
| 38 | | **Metrics** | "How's this trending over time?" — counters, gauges, distributions you can slice by attribute and chart, alert on, or compare across a deploy. | [Metrics](https://docs.sentry.io/product/explore/metrics/) | |
| 39 | |
| 40 | A useful mental split: a **log is one request's story** (the needle), a **metric is the aggregate** |
| 41 | (whether the haystack is normal), a **trace is where the time went**, and an **error is the thing |
| 42 | that needs a stack trace and an owner**. |
| 43 | |
| 44 | ## The Decision Table |
| 45 | |
| 46 | Use this as a gut check: |
| 47 | |
| 48 | | What you want to know | Reach for | |
| 49 | |-----------------------|-----------| |
| 50 | | Something crashed, show the stack trace | **Error** | |
| 51 | | How long did this take? Which step is slow? | **Traces / Spans** | |
| 52 | | Did the request flow through the steps I expected? | **Traces / Spans** | |
| 53 | | What was the state when the code made this decision? | **Log** | |
| 54 | | What did this function receive and return? | **Log** | |
| 55 | | How often does X happen? Is the rate normal? | **Metric** | |
| 56 | | Did something change after the deploy? | **Metric** | |
| 57 | |
| 58 | ## Resolving the Overlaps |
| 59 | |
| 60 | The same value can legitimately appear in more than one signal. These four tiebreakers cover almost |
| 61 | every real case. (Full reasoning, gotchas, and the "why not just log everything / emit one wide |
| 62 | event?" arguments live in [`references/choosing-signals.md`](references/choosing-signals.md).) |
| 63 | |
| 64 | - **Span attribute or metric?** Context about *one request's flow* that you want while reading that |
| 65 | trace → **span attribute** (it rides on the span in the waterfall). A standalone value you want |
| 66 | to chart, alert on, or slice over time across *all* requests → **metric**. The same number can |
| 67 | warrant both: `candidate_count` on the span to read one request, `recommendations.served` as a |
| 68 | metric to watch the rate. |
| 69 | - **Log or span?** The span is the timed node in the flow (mostly auto-instrumented, you rarel |