SherlockLiu Logo SherlockLiu
Back to all posts
Engineering

Practical OpenTelemetry — Part 11: Minimizing Adoption Friction

SL
Aug 23, 2026 9 min read
Practical OpenTelemetry — Part 11: Minimizing Adoption Friction

Every OpenTelemetry rollout eventually stops being a technical problem and becomes an organizational one. Chapter 11 of Practical OpenTelemetry is the first of two closing chapters that shift from how the standard works to how you actually get an organization to adopt it — and its central argument is a reframe worth carrying into any infrastructure rollout, not just this one: the way you roll something out determines whether it sticks.

Where to Start: Stability, Effort, Value

The book gives a genuinely useful three-factor framework for deciding which signal to enable first, rather than “do everything at once” or “whatever the loudest team wants”:

  • Stability — wait for a signal’s spec to stabilize before a broad rollout. An enablement team can and should test experimental features early, but shouldn’t bet a company-wide default on them.
  • Effort — tracing is usually the easiest signal, because auto-instrumentation (Part 4) does almost all the work. Logs are easy too, via appenders (Part 8). Metrics are rarely the easy one — dashboards, alerts, and runbooks all have to adapt to new names and semantic conventions, often requiring a period of dual-publishing old and new metric names side by side.
  • Value — tracing improves debugging immediately and, per Part 10, unlocks real sampling-driven cost savings. A team already running several metrics backends may reasonably prioritize metrics consolidation instead.

None of these factors dominates the others on their own — the book’s point is that they interact, and a rollout plan that ignores one of the three (usually effort) is the one that stalls.

The Enablement Function

The abstraction that makes broad adoption tractable is a telemetry enablement function — usually platform engineering — whose job is to make the golden path the easy path. Concretely, that means shipping opinionated defaults rather than leaving every team to rediscover the same decisions:

  • Exporters pointed at a gateway hostname, not a hardcoded backend URL — so a future vendor migration is a DNS change, not an org-wide config sweep (the exact mechanism Part 10’s gateway section argued for).
  • Correctly ordered propagators, chosen once instead of per-team (Part 5).
  • Instrumentation config, metric Views, and resource attributes, pre-tuned so teams don’t each independently discover the cardinality lessons from Part 7.
  • Pre-configured Collector agents, sidecars, and gateways (Part 9) — nobody hand-writes a memory_limiter block from scratch.
  • API shims for legacy OpenTracing/OpenCensus code — covered in full below, because they’re the actual migration mechanism, not just a nice-to-have.

Vendor distros fit the same shape from the vendor side: not forks, but public repositories under Apache v2.0, bundling either SDKs + plugins + opinionated defaults (client distros) or the same idea applied to the Collector (collector distros). The pattern — take the open standard, add curated defaults, ship it as your product — is the same one an internal enablement team runs, just commercialized.

Greenfield: Let Auto-Instrumentation Win

For a service with no existing telemetry, the book’s guidance is unambiguous: automatic instrumentation always takes precedence. Enable it in dev and staging first, extrapolate expected production volume from what you see there, and only reach for manual instrumentation (Part 6) for the domain-specific gaps auto-instrumentation can’t see.

The book’s own metaphor for signal balance is worth keeping: signals are like instruments in a song — over-relying on one doesn’t cover for the absence of the others. A service with beautiful traces and no metrics still can’t answer “is this within SLO” cheaply; a service with rich metrics and no traces still can’t answer “why,” which is the whole thesis Part 1 opened the series with.

Migrating Off OpenTracing and OpenCensus

This is the chapter’s most concrete section, and the one most rollouts actually need, since OpenTelemetry — as Part 2 covered — is itself the merger of these two predecessor projects.

The OpenTracing Shim: OpenTracingShim.createTracerShim(openTelemetry). What makes this a real migration path rather than a one-time cutover is Part 5’s composite propagators — OpenTelemetry can run the old and new propagation formats simultaneously, exporting in both old and new formats in parallel, so a transaction crossing a mix of migrated and unmigrated services never “breaks the chain.” Teams migrate service by service, not all at once.

Known incompatibilities to plan around:

  • OpenTracing treats baggage as part of tracing; OpenTelemetry splits it into its own signal (Part 5).
  • Span kind is immutable in OpenTelemetry once a span is created (Part 6); OpenTracing didn’t enforce this.
  • OpenTracing’s FOLLOWS_FROM relationship maps to an OpenTelemetry span Link — the same mechanism Part 6 used to keep fire-and-forget async tasks from corrupting a trace’s shape.
  • An OpenTracing error tag auto-maps to OpenTelemetry span status, but only in one direction.

The OpenCensus Shim bridges tracing and metrics simultaneously, loaded by reflection during Tracing initialization. Its incompatibilities are sharper: OpenCensus lets you specify a span’s parent after creation (OpenTelemetry doesn’t — parent is creation-time-only, same rule as SpanKind and Links); span links can be lost crossing the bridge; and OpenTelemetry has no equivalent of OpenCensus’s span-scoped samplers.

Migrating Off Prometheus and Statsd

The pattern here generalizes past Prometheus specifically: run a Collector sidecar that scrapes the existing metrics system while the app also exports new OTel metrics — migrating metric-by-metric instead of in one atomic cutover. To keep the two generations from colliding in the same backend during the overlap, tag new metrics with telemetry.sdk.name: opentelemetry so they land as genuinely distinct time series from the legacy ones. Statsd sidecars get replaced by Collectors through the identical mechanism.

Diagram of a gradual migration off OpenTracing: old and new instrumentation coexist behind a shim, with composite propagators keeping the trace chain intact across migrated and unmigrated services. Migrating Without Breaking the Chain Service A legacy OpenTracing unmigrated Service B OpenTracingShim mid-migration Service C native OpenTelemetry fully migrated Composite propagators: both formats travel on every hop otel.propagators=tracecontext,baggage,ot-format — nothing chosen wins by exclusion One trace can cross unmigrated, mid-migration, and migrated services without ever losing its shape.

Figure: composite propagators are what turn a migration from an atomic cutover into a gradual, service-by-service rollout.

Why This Chapter Matters More Than It Looks

Every technical decision in Parts 3 through 10 assumed telemetry already existed to configure. This chapter is the missing bridge: how a team with zero OpenTelemetry today, or with years of OpenTracing/OpenCensus/Prometheus-specific instrumentation already sunk into the codebase, actually gets from here to there without a company-wide stop-the-world migration. The mechanism that makes it possible — composite propagation formats running side by side — isn’t a new concept. It’s Part 5’s propagator design, applied to the hardest possible case: migrating the standard itself while production keeps running on it.

Part 12 closes the book — and this series — with what happens after the rollout succeeds: how to keep telemetry trustworthy, how to run postmortems that actually improve observability instead of just documenting incidents, and the book’s single most quotable line about how to govern all of it.


Next: Practical OpenTelemetry — Part 12: Adopting Observability — the effectiveness test, “enablement over control,” and the book’s closing philosophy.


References

Comments