Help us improve
Share bugs, ideas, or general feedback.
From honeycomb
Guides phased OpenTelemetry migration for existing uninstrumented apps: SDK setup, context propagation refactoring, logging/metrics bridges, verification. For retrofitting without breaking monitoring.
npx claudepluginhub honeycombio/agent-skill --plugin honeycombHow this skill is triggered — by the user, by Claude, or both
Slash command
/honeycomb:otel-migrationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Guide for retrofitting OpenTelemetry into an existing, uninstrumented application. This covers
Guides migration from Honeycomb Beelines (EOL) to OpenTelemetry instrumentation using two-phase W3C trace propagation and service-by-service replacement. Covers Go, Python, Node.js, Java, Ruby.
Instruments services with OpenTelemetry for RED metrics, structured logs, distributed tracing, and health checks. Outputs code/config for detected stacks like Node.js, Python, Go. Use for 'add monitoring', 'instrument', 'observability'.
Instrument a service with OpenTelemetry — RED metrics, structured logs, distributed tracing, and health checks. Outputs actual code and config, not a plan. Use when asked to "add monitoring", "instrument this", "add logging", "set up tracing", or "observability".
Share bugs, ideas, or general feedback.
Guide for retrofitting OpenTelemetry into an existing, uninstrumented application. This covers the phased migration approach, context propagation refactoring, logging and metrics bridges, and verification. This is distinct from greenfield OTel setup (see otel-instrumentation skill) and Beeline-specific migration (see beeline-migration skill).
Use this skill when the user has an existing application that:
For greenfield OTel setup, use the otel-instrumentation skill instead.
For Beeline-to-OTel migration, use the beeline-migration skill instead.
For understanding why to instrument, see the observability-fundamentals skill.
The migration follows six phases in order. Each phase is independently deployable and verifiable. Context propagation (Phase 3) is typically ~60% of the effort.
Set up TracerProvider, MeterProvider, and LoggerProvider with OTLP exporters. Wire initialization early in the application's entry point and shutdown in signal handlers.
Key guidance:
${CLAUDE_PLUGIN_ROOT}/skills/otel-instrumentation/references/sdk-setup-by-language.mdAdd OTel middleware to your HTTP framework. This gives you automatic spans for every inbound request with zero code changes to handlers. This is the highest-ROI step.
Critical: Different frameworks expose the OTel-enriched context differently. This is the #1
source of silent trace breaks. Consult
${CLAUDE_PLUGIN_ROOT}/skills/otel-migration/references/framework-middleware.md for
framework-specific details.
| Framework | How to get OTel context | Common mistake |
|---|---|---|
| Go net/http | r.Context() | N/A (standard) |
| Go Fiber v2 | c.UserContext() | Using c.Context() (returns fasthttp context without OTel span) |
| Go Gin | c.Request.Context() | Using c directly |
| Go Echo | c.Request().Context() | N/A |
| Python Flask | Automatic (thread-local) | N/A with instrumentation library |
| Python Django | Automatic (thread-local) | N/A with instrumentation library |
| Node.js Express | Automatic (AsyncLocalStorage) | N/A with instrumentation library |
| Java Spring | Automatic (thread-local) | Thread pool context loss |
| .NET ASP.NET Core | Automatic (AsyncLocal) | N/A |
| Ruby Rails | Automatic (thread-local) | N/A with instrumentation library |
Thread trace context through your call chain from HTTP handlers (or entry points) down to I/O operations. This is the hardest phase — typically ~60% of migration effort.
The difficulty of this phase varies dramatically by language:
context.Context parameter to every function in the call chain.contextvars propagates automatically within a thread. Pain points are
thread pools and multiprocessing.AsyncLocalStorage propagates through async/await automatically.
Pain points are old callback-based code.Activity propagates through async/await via AsyncLocal<T> automatically.For language-specific patterns and code examples, consult
${CLAUDE_PLUGIN_ROOT}/skills/otel-migration/references/context-propagation-patterns.md.
Add spans to business logic operations that auto-instrumentation doesn't cover. Defer to the
otel-instrumentation skill for span creation mechanics. Migration-specific guidance:
For attribute naming and span creation patterns, consult
${CLAUDE_PLUGIN_ROOT}/skills/otel-instrumentation/references/custom-instrumentation.md.
Replace or bridge your existing logging library into OTel so logs correlate with traces.
Key guidance:
For language-specific logging bridges and the multi-handler pattern, consult
${CLAUDE_PLUGIN_ROOT}/skills/otel-migration/references/bridge-libraries.md.
If you already have Prometheus metrics (or another metrics library), bridge them to OTel rather than rewriting.
Key guidance:
prometheus.NewCounterVec(...) calls continue unchanged/metrics endpoint if you have existing scrapers. The bridge adds OTLP
export in addition to scraping.For language-specific metrics bridges, consult
${CLAUDE_PLUGIN_ROOT}/skills/otel-migration/references/bridge-libraries.md.
After each phase, verify that instrumentation is correct and complete. Consult
${CLAUDE_PLUGIN_ROOT}/skills/otel-migration/references/verification-checklist.md for the
full checklist and query patterns.
For Honeycomb-specific verification queries, also consult the query-patterns skill.
For a catalog of common mistakes and how to avoid them, consult
${CLAUDE_PLUGIN_ROOT}/skills/otel-migration/references/migration-pitfalls.md.
For reference, a real migration of Gatus (~30k LOC Go, Fiber v2, SQLite/Postgres, Prometheus):
c.Context() vs c.UserContext(), printf-style slog format strings,
missing span.End() calls, goroutine context reuse