ADR-006: Pin OpenTelemetry Semantic Conventions to v1.26 as Platform Baseline
- Status: Proposed
- Date: 2026-05-07
- Authors: Amit Singh
- Deciders: Amit Singh — pending platform team review
- Supersedes: N/A
- Related RFC: N/A
- Project/Context: ShipSolid observability platform — Azure Container Apps (.NET + Python) on Grafana Cloud (Mimir + Loki + Tempo)
1. Context
The ShipSolid observability platform serves 50+ Azure Container Apps across 12+ engineering teams in two SDK languages (.NET 8 and Python 3.11+), exporting to Grafana Cloud. OpenTelemetry semantic conventions (semconv) define the canonical names and shapes of metrics, span attributes, and resource attributes — they are the schema contract that dashboards, alerts, and SLOs query against.
Three forces make an explicit version pin necessary:
- Breaking renames in upstream semconv. Between semconv 1.21 and 1.23,
http.server.durationwas renamed tohttp.server.request.duration, status code attribute moved fromhttp.status_codetohttp.response.status_code, and several queue / messaging attributes were renamed. SDK auto-instrumentation libraries follow these renames on their own release cadence. - Heterogeneous SDK upgrade cadence across teams. With 12+ teams owning their own service templates and dependency upgrades, two services in the same regional fleet can emit differently-named telemetry for the same operation if no platform pin is enforced. Dashboards built against one name silently lose half their data.
- Alert / dashboard contract. Recording rules, SLO definitions, and Grafana panels reference attribute names directly. Any silent rename invalidates the alerting layer without producing a “config error” — it produces missing data and false-quiet alerts.
The telemetry-schema-design.md document references semconv 1.26 as its
baseline (§15) but no standalone ADR captures the decision, the rejected alternatives, or the
upgrade process. Without a load-bearing ADR, a future SDK bump in any one service’s Dockerfile
could unilaterally break the platform’s observability contract.
2. Decision
Pin OpenTelemetry semantic conventions to v1.26 as the platform baseline for all ShipSolid Azure Container Apps services and the Grafana Alloy gateway tier, as established in ADR-008.
The pin is enforced at three layers:
- Service template (a-governance/service-template/) pins SDK package versions whose semconv-version metadata corresponds to 1.26.
- Alloy gateway runs the matching processor pipeline (e.g.,
transformrules expecting 1.26 attribute names). - Schema registry / dashboards reference attribute names from 1.26 only.
Bumping the platform-wide pin requires:
- A new ADR superseding this one.
- A cardinality and query-impact assessment against the dashboard inventory.
- A six-week dual-emission window (
emit_old: trueon the SDK exporter where the upstream library supports it, otherwise an Alloytransformprocessor that re-asserts old attribute names alongside new) before any dashboard or alert is migrated. - Dashboard and alert rule update PRs landing before the pin flips.
- Registry update with the new version.
3. Rationale
Why pin, and why 1.26?
Pinning is the only mechanism that prevents silent observability regression when a team upgrades an unrelated dependency. v1.26 is selected because:
- It is the most recent semconv release where the HTTP, queue, messaging, and database attribute
groups have all reached
stablestatus. Earlier (1.21) still hadhttp.server.durationas the canonical name; later “latest” trains still haveexperimentalflux in the database group. - Both
OpenTelemetry-DotNetandopentelemetry-pythonship contract-compatible releases that adopt 1.26 naming under their stable channels. - Mimir / Loki / Tempo in Grafana Cloud all accept 1.26-named attributes natively without bridge configuration.
Why not “track latest”?
Auto-tracking upstream means a 1.27 release in upstream OTel auto-propagates to whichever team
upgrades first. That team’s services emit new names; every other team continues emitting old names;
every dashboard breaks for a subset of services. The whole platform’s observability quality becomes
a function of who ran dotnet outdated last.
Why a dual-emission window?
Cutover-without-overlap means dashboards and alerts go dark between the SDK rollout and the dashboard migration. Dual-emission keeps the old name flowing alongside the new for the duration of the migration, removing the all-or-nothing failure mode.
4. Alternatives Considered
| Alternative | Reason for Rejection |
|---|---|
| Track upstream “latest” semconv | Silent platform-wide regression risk on every minor upstream release; no central control over upgrade timing |
| Pin per-team (no platform-wide baseline) | Same data shape diverges across services; cross-team dashboards become unreliable; recording rules cannot be authored once |
| Pin to v1.21 (pre-rename, fewer changes) | Forecloses access to stable HTTP/messaging conventions; locks the platform into an end-of-life version with no upstream patching |
Use only stable attributes, no version pin | Underspecified — “stable” is a per-version flag and changes between releases; doesn’t fix the silent-rename failure mode |
| Author ShipSolid-internal attribute schema and translate at the gateway | Maximum control but maximum work — duplicates upstream’s effort, adds a translation processor on every signal, alienates teams from the OTel ecosystem |
5. Consequences
Positive
- Single attribute schema across all services, all teams, both SDK languages.
- Recording rules and SLO definitions can be authored once and reused.
- Dashboard library (k-docs/technical-designs/grafana-tf/) can be templated against a known attribute set.
- Upgrades are deliberate, observable, and reversible (dual-emission window).
Negative / accepted costs
- Drift cost as upstream advances. v1.26 will eventually be N versions behind. The platform team accepts the cost of curating an upgrade ADR roughly every 12–18 months.
- Lock-out of newer SDK features tied to newer semconv. Teams cannot opportunistically adopt a 1.28-only feature without going through the upgrade ADR. The platform accepts this friction as the price of consistency.
- Service-template version pinning becomes a maintenance surface. The platform team owns keeping the template’s pinned SDK versions current with security patches without crossing the semconv boundary.
Follow-ups required
- Update a-governance/service-template/ (.NET and Python variants) to pin SDK package versions whose semconv metadata = 1.26. Document the pin alongside each pinned package.
- Add CI check in service templates that fails if
OpenTelemetry.SemanticConventions(or equivalent Pythonopentelemetry-semantic-conventions) resolves to a version outside the approved range. - Build the Alloy
transformdual-emission profile as a reusable module so the next ADR upgrade has plumbing already in place. - Update k-docs/system-designs/telemetry-schema-design.md §15 to reference this ADR by number.
- Author a runbook for the upgrade process (cardinality review → dual-emission → flip → tear-down).
6. Reconsideration Criteria
This decision should be revisited if any of the following occur:
- Upstream stabilises a new semconv major (e.g., v2.x) with non-cosmetic improvements — log conventions, GenAI, profiling — that the ShipSolid platform wants to adopt.
- Security or compliance vulnerability in a SDK version covered by the v1.26-compatible range, where the patched release also bumps semconv.
- Vendor (Grafana Cloud) deprecates support for v1.26-named attributes in Mimir / Loki / Tempo.
- Two or more ShipSolid services need an attribute that does not exist in v1.26, and the cost of waiting outweighs the upgrade cost.
- Recording-rule maintenance burden from the version lag becomes structurally larger than a planned upgrade would cost.
When triggered, author a new ADR proposing the new pinned version, the dual-emission timeline, and
the dashboard migration plan. Mark this ADR as Superseded and reference the new ADR.
7. References
- k-docs/system-designs/telemetry-schema-design.md §15 — Semantic Conventions Versioning
- OpenTelemetry semantic conventions repository
- OTel HTTP semconv stability statement (v1.23 stable promotion)
- ADR-002: Adopt Grafana Cloud for Unified Observability (lab)
- ADR-003: Adopt Grafana Cloud for Centralized Observability (ShipSolid platform)
Local graph
Linked from 4 notes
ADR-002: Adopt Grafana Cloud for Unified Observability
Accepted 2024-02-01 The Architect Learning Lab runs heterogeneous services across multiple technology stacks (.
ADR-007: Adopt Two-Tier Grafana Alloy Collector Topology
- **Status**: Proposed - **Date**: 2026-05-07
1 — OpenTelemetry SDKs & Semantic Conventions
OpenTelemetry is a specification and an API/SDK, not a backend — the pieces that make it up, and the semantic-convention vocabulary that lets two unrelated teams' telemetry be queried the same way.
01 — Platform Architecture
How the platform is built — views, planes, signals, and the decision record indexes.
Related notes
Signal Forge ADR-005: Separate collector configmaps per deployment mode
Keeps cloud and local Alloy collector configs in separate files rather than one conditional configmap, so each mode's exporters stay explicit and uncoupled.
Signal Forge ADR-003: Span metrics generated before tail sampling
Places the spanmetrics connector ahead of tail_sampling so RED metrics reflect all traffic instead of only the ~25% of traces that survive sampling.
Signal Forge ADR-002: SpanLink for async RabbitMQ propagation (not parent-child)
Uses a SpanLink, not a parent-child span relationship, to connect RabbitMQ consumer spans back to the producer span across async, retry-prone delivery.
Architecture Overview
Signal Forge's topology, service communication, trace propagation, and per-signal pipeline flow across local and Grafana Cloud deployment modes.