$npx -y skills add ollygarden/opentelemetry-agent-skills --skill otel-span-events-to-logs-migrationMigrate OpenTelemetry Span Events (AddEvent, RecordException, and language equivalents) to the Logs API following the accepted OTEP 4430 migration plan. Use when migrating instrumentation from span events to log-based events, reviewing code that still uses AddEvent or RecordExcep
| 1 | # Span Events to Logs Migration |
| 2 | |
| 3 | Use this skill to migrate instrumentation from the Span Event API (`AddEvent`, `RecordException`, and language equivalents) to the Logs API, following the accepted [OTEP 4430 deprecation plan](https://github.com/open-telemetry/opentelemetry-specification/blob/main/oteps/4430-span-event-api-deprecation-plan.md). |
| 4 | |
| 5 | ## Background |
| 6 | |
| 7 | The OpenTelemetry project accepted a plan to deprecate `Span.AddEvent` and `Span.RecordException` in favor of emitting events and exceptions through the Logs API. Span Events as a concept remain valid -- they can be emitted via logs that correlate to the active span, and optionally bridged back into the span proto. |
| 8 | |
| 9 | Status as of 2026-07-20: OTEP 4430 is accepted, log-based event/exception emission is specified in the Logs API, and the SDK "event to span event bridge" is specified with Development status. The trace API methods `AddEvent`/`RecordException` are not yet formally marked Deprecated in the specification -- that step is still pending. Treat existing span-event calls as migration candidates, not automatically invalid code; some SDK-specific equivalents have already changed status (for example OpenTelemetry .NET's `Activity.RecordException` extension is `[Obsolete]` in favor of `Activity.AddException`, which is still a span-event API). |
| 10 | |
| 11 | See `references/deprecation-plan.md` for the full context. |
| 12 | |
| 13 | ## Workflow |
| 14 | |
| 15 | 0. Prepare before migrating. |
| 16 | - check the project's OpenTelemetry SDK version supports log-based events (check the `manual-instrumentation` skill's version index if available) |
| 17 | - identify whether the project has a LoggerProvider configured; if not, one must be set up |
| 18 | - determine if downstream consumers (backends, dashboards, alerts) depend on span events appearing in the span proto envelope |
| 19 | |
| 20 | 1. Scan the codebase for span event usage. |
| 21 | - search for `AddEvent`, `add_event`, `addEvent`, `RecordException`, `record_exception`, `recordException`, `RecordError`, `AddException`, and language-specific variants |
| 22 | - categorize each call site: general event, exception recording, or informational annotation |
| 23 | - note the span context, attributes, and timestamp usage at each site |
| 24 | |
| 25 | 2. Classify each call site using the decision tree. |
| 26 | - see `references/decision-tree.md` for the full classification logic |
| 27 | - the three outcomes are: migrate to log-based event, convert to span attributes, or remove |
| 28 | |
| 29 | 3. Apply the migration for each call site. |
| 30 | - see `references/migration-patterns.md` for language-specific before/after patterns |
| 31 | - ensure the replacement log record carries the correct span context, event name, attributes, and timestamp; for exceptions use the applicable semantic-convention event name (normally an operation-specific `.exception` name), reserving `exception` for generic handlers |
| 32 | - for exceptions, preserve the applicable semconv attributes: `exception.type` and `exception.message` (at least one is required), plus `exception.stacktrace` when the language/error type makes it meaningful (in Go, omit it unless an error library preserves the origin stack -- do not call `runtime.Stack` at the emit site) |
| 33 | |
| 34 | 4. If backward compatibility is needed, configure the SDK bridge. |
| 35 | - see `references/backward-compat.md` |
| 36 | - this is an SDK-level log processor that converts log-based events back to span events |
| 37 | - only needed when downstream systems require span events in the same proto envelope as the span |
| 38 | |
| 39 | 5. Verify the migration. |
| 40 | |
| 41 | ## Required Completion Loop |
| 42 | |
| 43 | Follow this loop every time: |
| 44 | 1. scan and classify all span event call sites |
| 45 | 2. migrate each call site following the decision tree and patterns |
| 46 | 3. review the changed code against the checklist below |
| 47 | 4. re-open the changed files and confirm each checklist item with codebase evidence |
| 48 | 5. if any item is unresolved, patch the code or mark it not applicable with a reason, then repeat the review |
| 49 | 6. do not finish until every checklist item is completed or explicitly marked not applicable |
| 50 | |
| 51 | Do not mark a checklist item complete based on intent alone. Mark it complete only after confirming it in the current codebase. |
| 52 | |
| 53 | ## Migration Checklist |
| 54 | |
| 55 | For every item, report one of these statuses in the final answer: |
| 56 | - `[x]` completed |
| 57 | - `[~]` not applicable, with a reason |
| 58 | - `[ ]` unresolved |
| 59 | |
| 60 | Include file references as evidence for every completed item. |
| 61 | |
| 62 | - `[ ]` All general span-event call sites identified and classified, including `AddEvent` / `add_event` / `addEvent` and language equivalents such as .NET `ActivityEvent`. |
| 63 | - `[ ]` All exception span-event call sites identified and classified, including `RecordException` / `record_exception` / |