Skip to content

feat(semconv): add @maple/semconv, a checked-in OTel attribute registry - #1191

Merged
Makisuo merged 1 commit into
mainfrom
feat/semconv-registry-lib
Sep 30, 2026
Merged

Makisuo merged 1 commit into
mainfrom
feat/semconv-registry-lib

feat(semconv): add @maple/semconv, a checked-in OTel attribute registry

d01a0b9
Select commit
Loading
Failed to load commit list.
Maple Review Bot / Maple / review completed Sep 30, 2026 in 3m 46s

Confidence 3/5 · 1 issue to address

🟡 Confidence 3/5 · needs attention
Contained, unconsumed data library, but canonicalKey mis-walks obsoleted keys on the checked-in snapshot and nothing tests that branch.
quality 90/100 · 1 warning · tests partial · risk low

Adds @maple/semconv, a checked-in snapshot of the semconv and GenAI attribute registries plus lookup helpers (attributeStatus, canonicalKey, legacyKeys, isRegistryKey). Nothing consumes it yet; the only issue is that canonicalKey walks obsoleted keys, which the snapshot exercises.

  • attributeStatus classifies keys current/moved/deprecated/removed/unknown, templates included
  • canonicalKey follows single-successor deprecations; legacyKeys indexes the reverse map

Findings

🟠 Warning · F1 · canonicalKey follows obsoleted successors, contradicting its own contract

correctness · lib/semconv/src/registry.ts:110

The loop stops only on successors.length !== 1 and never reads deprecation.reason, so an obsoleted key with a single successor is rewritten even though the doc above promises obsoleted keys are returned unchanged (and reason is otherwise dead: nothing in the package reads it). On the checked-in snapshot this changes real keys: canonicalKey("error.message") returns feature_flag.error.message — and consequently legacyKeys("feature_flag.error.message") lists error.message — and db.instance.id is rewritten to elasticsearch.node.name. A consumer deriving the Maple rename/alias tables from this package would fold generic error.message into a feature-flag key.

		if (
			status.kind !== "deprecated" ||
			status.definition.deprecation.reason === "obsoleted" ||
			status.successors.length !== 1
		)
			return current
What was checked
  • Ran the package's head code under node against the checked-in snapshot (--experimental-strip-types) for attributeStatus, canonicalKey, legacyKeys, definitions
  • Every deprecation-successor in the snapshot resolves to a registry key; template matching (http.request.header.x, container.label.x) picks the expected definition
  • The moved heuristic holds on the data: all 56 moved keys are live in genai with a semconv stub, none the other way

d01a0b9 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

Annotations

Check warning on line 110 in lib/semconv/src/registry.ts

See this annotation in the file changed.

@maple-review-bot maple-review-bot / Maple / review

correctness: `canonicalKey` follows `obsoleted` successors, contradicting its own contract

The loop stops only on `successors.length !== 1` and never reads `deprecation.reason`, so an *obsoleted* key with a single successor is rewritten even though the doc above promises obsoleted keys are returned unchanged (and `reason` is otherwise dead: nothing in the package reads it). On the checked-in snapshot this changes real keys: `canonicalKey("error.message")` returns `feature_flag.error.message` — and consequently `legacyKeys("feature_flag.error.message")` lists `error.message` — and `db.instance.id` is rewritten to `elasticsearch.node.name`. A consumer deriving the Maple rename/alias tables from this package would fold generic `error.message` into a feature-flag key.